A Case Study of Participant Feedback for a Teaching Remotely Professional Learning Course

This case study serves as the final project for the ECI 588 Text Mining in Education course offered in spring 2021 at North Carolina State University. This course is part of the Learning Analytics Certificate Program.

The Rmarkdown file can be downloaded from the code folding control button in the upper right hand of this page. The full R Studio project can be access via this Github repository. However, it should be noted that the data for this project is not included because it requires special permission for sharing.

Context of this Case Study

The data source for my final project consists of the end of course survey responses for the “Teaching Remotely: A Practical Guide” 2020 MOOC-Ed course offered by the Friday Institute for Educational Innovation. This professional learning course was offered to help educators address the key issues of transitioning to Emergency Remote Learning due to the COVID-19 global pandemic. The course objectives covered key professional development areas for teaching remotely such as establishing norms for remote learning, bring social-emotional learning to the virtual classroom, maintaining connections with student and families, digital content selection, supporting learners with special needs, and providing quality feedback. You can read more about the course on the Friday Institute’s Professional Learning and Collaboration Environment course site.

The raw data includes 3,080 end of course survey responses where participants provided their ratings for overall effectiveness of the course, their perceived effectiveness of particular aspects of the course, their estimated number of hours spent engaged in the course activities, and their ratings for how effectively the course improved their practice. The main focus of my project for this course will be the open-ended, unstructured text responses that participants provided in answer to the following questions:

  • What was the most valuable aspect of this course in supporting your personal or professional learning goals?

  • In what ways, if any, do you anticipate applying the knowledge, skills, and/or resources you acquired from this course to your professional practice?

  • Please describe any changes you have made to your practice, including how you have applied the knowledge, skills, and/or resources you gained in this course.

  • What recommendations do you have for making this course more valuable to future participants (e.g., other resources, additional features, activities, etc.)? Please explain.

Guiding Questions

I am interested in this data/context because I am heavily involved in developing educator professional development and this analysis may help guide such development. In particular, my guiding questions for this case study will be:

  1. What aspects of the Teaching Remotely professional development course do participants find most valuable?

  2. What changes, if any, are being made to participants’ practice as a result of their participation in this course?

  3. If participants found the course to be ineffective, what specific recommendations have they made for its improvement?

  4. How do the sentiments of participants’ open-ended responses compare to their ratings of the course’s overall effectiveness?

Target Audience

My target audience is any other researcher or teacher educator who, like myself, is interested in making improvements to their own professional development offerings. I hope that the analysis will help identify “best practices” by examining the components of professional learning that are most valuable as well as specific areas that could be targeted for improvement.

Limitations of this Case Study

Before diving into the analysis of this data, it is important to note that responses to the end of course survey were voluntary. Therefore, it is possible that those participants who did not complete all of the activities or that found the course to be ineffective did not respond to the end of course survey. Examining the data does show that the ratings for overall effectiveness of the course is skewed very positively which confirms that a key limitation for this case study lies in the response rates for those participants who only completed a portion of the course or were dissatisfied with the course content in some manner.

End of Course Survey Analysis

In the following sections, the processes used to analyze the end of course survey data are described and findings are presented.

Data Wrangling

My initial pre-processing of the data began with removing some HTML formatting that appears in text responses and setting column names that are more readable than those assigned by the survey system. I chose not to omit NA values at this point simply because there was at least one in every response and that resulted in no data left to analyze! Instead, I omit the NA values at appropriate points throughout my analysis. Additionally, since some cursory exploration of the data showed that participants made mention of specific unit numbers, I also chose not to remove numbers/digits from the text responses when I pre-processed the data. The following shows the clean column names and a glimpse of the data contained in the end of course survey responses.

eoc_survey_data <- read_csv("data/eoc_surveydata_wrangled_grouped.csv") %>% 
  select(response,
         EffectivenessRating,
         IntroDiscussionRating,
         CourseContentRating,
         PuttingItTogetherRating,
         ActionPlanRating,
         ResourcesRating,
         MostValuableAspects,
         ImprovementEstablishingNorms,
         ImprovementBringingSEL,
         ImprovementMaintainingConnection,
         ImprovementSelectDigResources,
         ImprovementSupportSpecialPop,
         ImprovementProvidingFeedback,
         PositiveChangesEffectiveness,
         HasAttemptedChanges,
         AnticipatedApplicationPractice,
         ChangesToPractice,
         CourseRecommendations,
         DesiredActivityCompletion,
         CourseHoursEstimate,
         text) %>% 
  mutate(CourseHoursEstimate = as.factor(CourseHoursEstimate)) %>% 
  mutate(CourseCompletion = as.factor(ifelse(DesiredActivityCompletion == 0, "incomplete", "complete"))) %>% 
  filter(response != 87684,
         response != 89417)
glimpse(eoc_survey_data)
## Rows: 3,078
## Columns: 23
## $ response                         <dbl> 80338, 87032, 89153, 79595, 92739, 81…
## $ EffectivenessRating              <dbl> 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 2…
## $ IntroDiscussionRating            <dbl> 1, 1, 2, 2, 2, 3, 2, 3, 3, 2, 1, 2, 2…
## $ CourseContentRating              <dbl> 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 2…
## $ PuttingItTogetherRating          <dbl> 1, 1, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2…
## $ ActionPlanRating                 <dbl> 1, 2, 2, 2, 3, 2, 2, 2, 2, 3, 1, 2, 3…
## $ ResourcesRating                  <dbl> 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 1, 2…
## $ MostValuableAspects              <chr> "I loved all of the attached resource…
## $ ImprovementEstablishingNorms     <dbl> 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1…
## $ ImprovementBringingSEL           <dbl> 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2…
## $ ImprovementMaintainingConnection <dbl> 1, 1, 2, 1, 2, 2, 2, 3, 1, 2, 1, 2, 2…
## $ ImprovementSelectDigResources    <dbl> 1, 2, 2, 3, 3, 2, 2, 2, 2, 2, 1, 2, 2…
## $ ImprovementSupportSpecialPop     <dbl> 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1…
## $ ImprovementProvidingFeedback     <dbl> 1, 1, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 1…
## $ PositiveChangesEffectiveness     <dbl> 1, 1, 1, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1…
## $ HasAttemptedChanges              <dbl> 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3…
## $ AnticipatedApplicationPractice   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ChangesToPractice                <chr> "I really like the ideas with the stu…
## $ CourseRecommendations            <chr> "I think that I made recommendations …
## $ DesiredActivityCompletion        <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1…
## $ CourseHoursEstimate              <fct> 1 : 1-2 hours per unit, 2 : 3-4 hours…
## $ text                             <chr> "i loved all of the attached resource…
## $ CourseCompletion                 <fct> complete, complete, complete, complet…

As you will notice, two of the survey responses were discarded due to corrupted character encodings within the text responses. I believe this may have been due to participants copying and pasting material into their responses. The following sections present my analysis of the Teaching Remotely MOOC-ED end of course survey responses arranged by the guiding questions that frame the case study.

Most Valuable Aspects

The first guiding question for my analysis is:

What aspects of the Teaching Remotely professional development course do participants find most valuable?

Based on the nature of the responses, which are pretty short, the text was tokenized and stop words were removed. Since the responses contained some HTML from the survey system, custom stop words were also employed for the tokenization process (e.g., “nbsp” or “amp”). It should be noted that some of the MOOC-Ed participants chose not to respond to the survey question: “What was the most valuable aspect of this course in supporting your personal or professional learning goals?” Therefore, I had to do some further pre-processing at this stage and omit any NA values that were lurking in the data.

eoc_aspects <- eoc_survey_data %>%
  select(response, MostValuableAspects) %>%
  slice(-1, -2) %>%
  na.omit()

eoc_aspects %>% 
  select(MostValuableAspects)
## # A tibble: 3,076 x 1
##    MostValuableAspects                                                          
##    <chr>                                                                        
##  1 Learning about teaching remotely and how it affects teachers and students.&n…
##  2 To see that the effort of the last few months and my long-term engagement ha…
##  3 Discussion responses&nbsp;                                                   
##  4 I am going to rethink my way of working.&nbsp;                               
##  5 Validation of what my district and myself are doing as remote teaching conti…
##  6 I think the resources that were provided in the course were most helpful for…
##  7 It is obviously very timely!&nbsp; I like having a structure to start applyi…
##  8 I liked seeing examples to get ideas to use with my students.                
##  9 The numerous resources and strategies provided                               
## 10 I really enjoyed the videos from all of the units.&nbsp; The links and resou…
## # … with 3,066 more rows

Custom stop words were employed for the leftover HTML that crept into the responses (e.g., nbsp or amp) and for words that were simply a restating of the survey prompt (e.g., valuable and aspect) as part of the response.

custom_stop <- data.frame("word" = c("nbsp",
                                     "amp",
                                     "NA",
                                     "N/A",
                                     "N/a",
                                     "Na", 
                                     "na",
                                     "aspect", 
                                     "valuable"))

eoc_tidy_aspects <- eoc_aspects %>% 
  unnest_tokens(word, MostValuableAspects) %>%
  anti_join(stop_words) %>% 
  anti_join(custom_stop)

Below you can see the words that appear in the question responses at least 150 times. Resources is at the top of the list, but ignoring some words like helped or helpful there are others that stand out such as ideas, links, videos, articles, feedback, and discussion.

eoc_tidy_aspects %>% 
  dplyr::count(word, sort = TRUE) %>% 
  filter(n > 150) %>% 
  mutate(word = reorder(word, n)) %>% 
  ggplot(aes(n, word)) + 
  theme_minimal() +
  geom_col(fill="#7B0D1E") + 
  labs(y = NULL)

It was at this point that I decided to examine bigrams for this question. As you can see in the bar chart, some of the most frequently used words are plan and unit. These often appear in the responses as part of phrases, such as “action plan” or “unit 3” and I hoped to capture more specific valuable aspects of the MOOC-Ed such as these if at all possible.

eoc_aspects_bigrams <- eoc_aspects %>%
  unnest_ngrams(bigram, MostValuableAspects, n = 2, to_lower = TRUE) 

eoc_separated_aspects <- eoc_aspects_bigrams %>%  
  separate(bigram, into = c("word1", "word2"), sep = " ") %>% 
  na.omit()

eoc_united_aspects <- eoc_separated_aspects %>%
  filter(!(word1 %in% stop_words$word), 
         !(word2 %in% stop_words$word)) %>%  
  filter(!(word1 %in% custom_stop$word), 
         !(word2 %in% custom_stop$word)) %>%
  unite(bigram, c(word1, word2), sep = " ")

bigram_counts_aspects <- eoc_united_aspects %>%
  dplyr::count(bigram, sort = TRUE) %>%
  top_n(25)

As you can see from the word cloud below, examining the bigrams was actually fruitful. It revealed that aspects like “action plan”, “learning goals”, “unit 5”, and “unit 6” were mentioned quite frequently by those who responded to the end of course survey. It also revealed other key content like “social emotional”, “special education”, “establishing norms” and “digital citizenship”.

wordcloud2(bigram_counts_aspects, size = 2, shape='circle', color='#7B0D1E')

Changes to Practice

The second guiding question for my analysis is:

What changes, if any, are being made to participants’ practice as a result of their participation in this course?

Answering this question focuses in on the following two survey questions:

  • In what ways, if any, do you anticipate applying the knowledge, skills, and/or resources you acquired from this course to your professional practice?
  • Please describe any changes you have made to your practice, including how you have applied the knowledge, skills, and/or resources you gained in this course.

Responses to these questions were captured in the dataframe columns called AnticipatedApplicationPractice and ChangesToPractice. Let’s first focus on the changes that participants anticipated making to their practice. We’ll just grab the AnticipatedApplicationPractice column from our dataframe and do some further pre-processing by stripping out lingering HTML tags and responses where the participants just wrote some variant of “N/A.”

anticipated_changes <- eoc_survey_data %>%
  select(response, AnticipatedApplicationPractice) %>%
  mutate(AnticipatedApplicationPractice = gsub('&nbsp;', ' ', AnticipatedApplicationPractice)) %>% 
  mutate(AnticipatedApplicationPractice = gsub('&amp;', ' ', AnticipatedApplicationPractice)) %>%
  slice(-1, -2) %>%
  na.omit() %>% 
  filter(AnticipatedApplicationPractice != 'N/A')

anticipated_changes %>% 
  select(AnticipatedApplicationPractice)
## # A tibble: 78 x 1
##    AnticipatedApplicationPractice                                               
##    <chr>                                                                        
##  1 "I have made copies of several of the articles.  I will continue to read the…
##  2 "I plan to incorporate knowledge into my tutoring sessions."                 
##  3 "I plan to share the ideas provided through professional development with ad…
##  4 "I would like to apply the SEL info   maintaining relationships."            
##  5 "I plan on being more cautious with the online materials that I send my stud…
##  6 "I've selected the resources I think most apply to my school community and w…
##  7 "I know that I will immediately apply many of the skills such as defined nor…
##  8 "We plan to use many of the resources made available."                       
##  9 "I plan on usinsome of the strategies that I read about in the units."       
## 10 "The knowledge I learned from this will be applied in my professional practi…
## # … with 68 more rows

There are only 78 responses to this survey question about anticipated changes to participants’ professional practice, so we’ll just grab a sampling of those to examine them for any patterns. In particular, we will target the responses that specifically mention a participant’s “plan” and grab ten of those to read more closely.

changes_quotes <- anticipated_changes %>%
  select(AnticipatedApplicationPractice) %>% 
  filter(grepl('plan', AnticipatedApplicationPractice))

sample_changes <- sample_n(changes_quotes, 10)
kable(sample_changes)
AnticipatedApplicationPractice
I wanted to answer the last question honestly because I have not started to actually plan for this year. I have bookmarked many of the resources and will print out and laminate them for constant reference. I will use videos to introduce myself and record lessons. I will incorporate digital citizenship in my lessons and create a very structured and routine remote learning platform for my class. I have also bookmarked the parent/student surveys which I will use frequently to elicit feedback.
I plan on being more cautious with the online materials that I send my students. I also plan on focusing a lot on SEL and maintaining connections with my students.
the reason why I clicked “no” was that at the time of doing this course our school system was on vacation so there would have been no way to implement that which was learnt. That being said, There is clear intent on my part to implement content learnt. How do I plan on doing this? With the online class beginning in earnest from September 1st 2020, The notes that I have gathered will be used to create the environment of learning for my class, the mode of feedback and assessment and the atmosphere for learning and achievement for both students and parents.
I plan on usinsome of the strategies that I read about in the units.
I plan to look at some of the new resources that I learned about that may be better then ones that I am presently using. I hope to find the easiest and more effective ones to use with my students.
I plan to focus my attention on starting the year with plenty of relationship Building activities online (since we are beginning remotely), being sure to check in with my students and their parents on a regular basis to ensure how they are feeling, Proving links to the content I include and giving credit to the owner of it when necessary. This will also allow students to access it if needed. Being more alert to the needs of my disabled students To ensure they are able to continue learning. I will also be more consistent and specific in my feedback.
I plan to establish norms differently than I would in the classroom when I meet my kids next week through a Google Meet. I will be using some of the resources such as ck-12 when I am teaching. I will remember the importance of parent communication during remote learning and be more aware of what I can do to help parents in order to help their students.
I plan to utilize the techniques and resources from this course for the fall. Further, I hope to encourage and teach others in my department how to use these resources.
I plan on using a contract to clearly lay out expectations for all parties involved.
I plan to use many of the resources provided in my classroom, especially with assessments and reaching special needs students. I plan to start my course off with discussion digital citizenship which is something I usually don’t formally do.

Even with just this handful of responses, we can see that participants plan to: 1) establish norms and provide social-emotional learning (SEL) through relationship-building activities in their virtual classrooms; 2) maintain effective communication with students and their families; 3) and share the content they learned with colleagues. Since some of these are learning objectives for the MOOC-Ed Teaching Remotely course, these responses appear to indicate that participants can envision how the course content aligns with and how they can apply it to their own professional practice.

Now that we have seen how participants anticipate applying the course content, let’s examine the changes they indicate they have already made to their practice. In this case, we’ll concentrate on the ChangesToPractice column of our dataframe.

practice_changes <- eoc_survey_data %>%
  select(response, ChangesToPractice) %>%
  mutate(ChangesToPractice = gsub('&nbsp;', ' ', ChangesToPractice)) %>% 
  mutate(ChangesToPractice = gsub('&amp;', ' ', ChangesToPractice)) %>%
  slice(-1, -2) %>%
  na.omit() %>% 
  filter(ChangesToPractice != 'N/A')

practice_changes %>% 
  select(ChangesToPractice)
## # A tibble: 2,565 x 1
##    ChangesToPractice                                                            
##    <chr>                                                                        
##  1 "While I'm not actually teaching at the moment, I have implemented those ste…
##  2 "I consider the online resources I choose more carefully. "                  
##  3 "I will have to think about  assessment and special needs in my teaching  pr…
##  4 "I will focus on setting technology use norms with my students and families.…
##  5 "My 7th grade team is in the process of creating our norms before school sta…
##  6 "Just getting started, but great ideas to apply"                             
##  7 "I have cut back on the workload and found ways to help struggling learners.…
##  8 "I have included in my action plan key strategies to work on starting with c…
##  9 "I loved the last two units and am planning on focusing a lot on making sure…
## 10 "I have begun to redesign my learning materials ensuring that I utilize the …
## # … with 2,555 more rows

Looking at the tokenized responses to this survey question reveals that participants will focus changes to their practice on students, resources, feedback, norms, and SEL. They also frequently mention tools, planning, assessment, and communication.

eoc_tidy_changes <- practice_changes %>% 
  unnest_tokens(word, ChangesToPractice) %>%
  anti_join(stop_words)

eoc_tidy_changes %>% 
  dplyr::count(word, sort = TRUE) %>% 
  filter(n > 150) %>% 
  mutate(word = reorder(word, n)) %>% 
  ggplot(aes(n, word)) + 
  theme_minimal() +
  geom_col(fill="#7B0D1E") + 
  labs(y = NULL)

Since these unigrams only convey where participants will focus their changes to practice, I decided to also examine bigrams here to get a clearer picture of the changes participants have made to their classroom practices.

eoc_changes_bigrams <- practice_changes %>%
  unnest_ngrams(bigram, ChangesToPractice, n = 2, to_lower = TRUE) 

eoc_separated_changes <- eoc_changes_bigrams %>%  
  separate(bigram, into = c("word1", "word2"), sep = " ") %>% 
  na.omit()

eoc_united_changes <- eoc_separated_changes %>%
  filter(!(word1 %in% stop_words$word), 
         !(word2 %in% stop_words$word)) %>%
  unite(bigram, c(word1, word2), sep = " ")

token_counts_changes <-  eoc_tidy_changes %>% 
  dplyr::count(word, sort = TRUE)

bigram_counts_changes <- eoc_united_changes %>% 
  dplyr::count(bigram, sort = TRUE) %>% 
  top_n(25)
wordcloud2(bigram_counts_changes, size = 2, shape = 'circle', color = '#7B0D1E')



The top 25 bigrams shown in the word cloud above suggest that participants have already made changes to their professional practice that include establishing norms, holding office hours, making an action plan or lesson plans, check ins, providing feedback, and using Google Classroom. However, many of the bigrams imply the same changes with different wordings, such as “providing feedback” and “provide feedback” or “virtual learning” and “online learning.” This suggests that future analyses may benefit from stemming.

Recommendations for Improvement

The next guiding question for this case study deals with participants’ recommendations for course improvements:

If participants found the course to be ineffective, what specific recommendations have they made for its improvement?

Specifically, it focuses on the responses from participants who rated the overall effectiveness of the course as Neither effective nor ineffective, ineffective, or very ineffective. The response text comes from the CourseRecommendations column of the dataframe.

participant_recommendations <- eoc_survey_data %>%
  select(response, EffectivenessRating, CourseRecommendations) %>%
  mutate(CourseRecommendations = gsub('&nbsp;', ' ', CourseRecommendations)) %>% 
  mutate(CourseRecommendations = gsub('&amp;', ' ', CourseRecommendations)) %>%
  slice(-1, -2) %>%
  na.omit() %>% 
  filter(CourseRecommendations != 'N/A', 
         CourseRecommendations != 'n/a',
         EffectivenessRating >= 3)

participant_recommendations %>% 
  select(EffectivenessRating, CourseRecommendations)
## # A tibble: 69 x 2
##    EffectivenessRating CourseRecommendations                                    
##                  <dbl> <chr>                                                    
##  1                   3 "Including more online student activities people have fo…
##  2                   3 "Because I was rushed through it, make sure future parti…
##  3                   4 "Somehow I would like a little more interaction with oth…
##  4                   3 "Sharable contents and folders with activities in google…
##  5                   3 "I don't have any."                                      
##  6                   3 "With remote learning being new it is hard to even provi…
##  7                   5 "I think the course was one of the best I have taken."   
##  8                   5 "I thought unit 3 needed more tips for finding online op…
##  9                   5 "The copyright module got a little technical for my unde…
## 10                   5 "In some topics you have a lot of links and a lot of res…
## # … with 59 more rows
recs_stop <- data.frame("word" = c("n/a", "N/A", "N/a"))

eoc_tidy_recs <- participant_recommendations %>%
  unnest_tokens(word, CourseRecommendations) %>%
  anti_join(stop_words) %>% 
  anti_join(recs_stop)

eoc_tidy_recs %>% 
  dplyr::count(word, sort = TRUE) %>% 
  filter(n > 2) %>% 
  mutate(word = reorder(word, n)) %>% 
  ggplot(aes(n, word)) + 
  theme_minimal() +
  geom_col(fill="#7B0D1E") + 
  labs(y = NULL) 

After tokenization, the words most frequently used in response to the survey question “What recommendations do you have for making this course more valuable to future participants?” are words like videos, time, teachers, resources. In fact, on the whole the tokenized text closely resembles the results from examining the other text responses. Therefore, a closer look into the raw data may be helpful. We’ll grab a sampling of the responses from the ratings of Neither effective nor ineffective, ineffective, or very ineffective and read through them.

recs_quotes <- participant_recommendations %>% 
  select(response, EffectivenessRating, CourseRecommendations) %>% 
  filter(EffectivenessRating >= 3,
         CourseRecommendations != 'none',
         CourseRecommendations != 'N/a')

sample_neutral <- recs_quotes %>% 
  filter(EffectivenessRating == 3) %>% 
  sample_n(5) %>% 
  select(CourseRecommendations)

sample_ineffective <- recs_quotes %>% 
  filter(EffectivenessRating == 4) %>% 
  select(CourseRecommendations)

sample_veryineffective <- recs_quotes %>% 
  filter(EffectivenessRating == 5) %>% 
  sample_n(5) %>% 
  select(CourseRecommendations)
  
sample_recs <- rbind(sample_neutral, sample_ineffective, sample_veryineffective)

kable(sample_recs)
CourseRecommendations
Please acknowledge that there is a population of students with disabilities that just cannot attend to remote learning. These families are being left behind and their teachers are feeling completely lost and overwhelmed. I get it, there are amazing resources for remote learning out there and I have spent much of my work days so far taking multiple required courses and trainings learning about them but I cannot use them.
I don’t have any.
Too long.
Shorting Unit 6
This course is very redundant. There is a lot of information repeated in different ways, but it is still the same information and it’s not difficult information to grasp. Also, I felt like the course just bombarded me with educator blog posts, again on repetitive topics, and they were just anecdotal posts that created lists of stuff people should do. I think focusing on fewer, more research based resources would be more effective.
Somehow I would like a little more interaction with other participants. The posting was not as effective because it seemed there was not enough authentic engagement. One suggestion would be to have optional online, live discussions to further the conversations.
More information on children with Disabilities!
More interaction – zooms?
I found the course to be very valuable! I don’t have any suggestions.
I have no recommendations. I would keep it as is.
Maybe more practical examples on how some those best practices work, especially for lower level students.
In some topics you have a lot of links and a lot of resources to read. It becomes overwhelming. Pick two or three.
I think the course was one of the best I have taken.

Reading through these results, some key issues are highlighted in these responses. For example, multiple participants in this sample suggests a lack of course content addressing remote teaching strategies for supporting students with disabilities. Other responses suggest that the course needed more interaction between participants or that course content was too long and/or repetitive. However, and perhaps somewhat surprisingly, some responses suggest that the course is sufficient and very valuable despite low overall effectiveness ratings. Thus, the next step in this case study will be to perform sentiment analysis on the participants’ text responses and compare that to the overall effectiveness ratings that participants gave to the course.

Participants’ Sentiments Compared to Course Ratings

The final guiding question for this study is:

How do the sentiments of participants’ open-ended responses compare to their ratings of the course’s overall effectiveness?

To answer this question, the response text of all three open-ended survey items was combined into a single text entry for each survey response. Additionally, participants’ ratings for the course’s overall effectiveness were adapted from the 5-point Likert scale (very effective to very ineffective) to a 3-point sentiment scale. That is, ratings of very effective and effective were collapsed to represent positive sentiment, neither effective nor ineffective represents a neutral sentiment, and very ineffective and ineffective were collapsed to represent a negative sentiment. Then proportions of the resulting course rating sentiments were calculated to make comparison to the results of sentiment analysis using the Valence Aware Dictionary and sEntiment Reasoner (VADER) package.

courseRatings_results <- eoc_survey_data %>%
  mutate(sentiment = ifelse(EffectivenessRating == 5, "negative",
                        ifelse(EffectivenessRating == 4, "negative",
                               ifelse(EffectivenessRating == 3, "neutral",
                                      ifelse(EffectivenessRating == 2, "positive", "positive"))))) %>%
  dplyr::count(sentiment, sort = TRUE) %>%
  na.omit() %>% 
  mutate(proportion = n / sum(n)) %>% 
  mutate(lexicon = "Participant Rating Sentiment") 

courseRatings_results
## # A tibble: 3 x 4
##   sentiment     n proportion lexicon                     
##   <chr>     <int>      <dbl> <chr>                       
## 1 positive   2847    0.968   Participant Rating Sentiment
## 2 neutral      77    0.0262  Participant Rating Sentiment
## 3 negative     18    0.00612 Participant Rating Sentiment
survey_resp_text <- eoc_survey_data

summary_vader <- vader::vader_df(survey_resp_text$text) %>% 
  select(text, compound, pos, neg, neu)

vader_results <- summary_vader %>%
  mutate(sentiment = ifelse(compound > 0, "positive",
                            ifelse(compound < 0, "negative", "neutral"))) %>%
  dplyr::count(sentiment, sort = TRUE) %>%
  na.omit() %>%
  mutate(proportion = n / sum(n)) %>%
  mutate(lexicon = "Vader Sentiment")

vader_results
##   sentiment    n proportion         lexicon
## 1  positive 2648 0.86029890 Vader Sentiment
## 2   neutral  359 0.11663418 Vader Sentiment
## 3  negative   71 0.02306693 Vader Sentiment

As you can see from the results below, the sentiment analysis of the open-ended responses appears to align with the sentiments of participants’ course ratings. This is despite some results above where participants rated the course to be ineffective or neither effective nor ineffective but stated that they liked the course as if and would not recommend changes.

comparison_df <- rbind(vader_results, courseRatings_results)

ggplot(comparison_df, aes(x = sentiment, y = proportion, fill = sentiment)) +
  geom_col() +
  facet_grid(. ~ lexicon) +
  theme_minimal() +
  theme(legend.position="none") +
  theme(plot.title = element_text(hjust = 0.5)) +
  xlab("Sentiment") +
  ylab("Proportion") +
  ggtitle("Sentiment Comparison of Participants' Ratings and Vader Analysis Results")

For a deeper look at participants’ sentiments as expressed through their text responses, I also decided to use the NRC sentiment lexicon to examine the range of emotions expressed across the survey responses. The results of this analysis are shown below.

nrc <- get_sentiments("nrc")

survey_stop <- data.frame("word" = c("nbsp", "NA", "N/A", "n/a", "na", "amp"))

participant_tokens <- eoc_survey_data %>%
  select(response, text) %>%
  unnest_tokens(word, text) %>%
  anti_join(stop_words) %>%
  anti_join(survey_stop)

sentiment_nrc <- inner_join(participant_tokens, nrc, by = "word")

summary_nrc <- sentiment_nrc %>%
  dplyr::count(sentiment, sort = TRUE) %>%
  spread(sentiment, n) %>%
  mutate(lexicon = "nrc") %>%
  relocate(lexicon) %>% 
  select(anger, anticipation, disgust, fear, joy, sadness, surprise, trust)

kable(summary_nrc)
anger anticipation disgust fear joy sadness surprise trust
395 4653 176 794 6229 643 1003 10278

As you can see, participants’ most frequently exhibited trust in their responses along with anticipation and joy. The least frequent emotions exhibited were anger and disgust. Again, these results support that, of those participants who responded to the end of course survey, overall satisfaction with the course content was skewed very positively.

Since the course ratings and sentiments are skewed so positively and a stated limitation of this data is a potentially low response rate for those who did not complete the course activities, we’ll examine the proportion of responses that indicate participants’ ability to complete all the activities they wanted to complete during the course. The survey item that provides the data for this part of the analysis is the yes or no question:

Were you able to complete all of the activities that you wanted to complete in this course?

Note here that we are considering a yes response to mean “complete” and a no response to mean “incomplete.”

courseCompletion_results <- eoc_survey_data %>% 
  select(CourseCompletion) %>% 
  dplyr::count(CourseCompletion, sort = TRUE) %>%
  mutate(proportion = n / sum(n))

kable(courseCompletion_results)
CourseCompletion n proportion
complete 2958 0.9610136
incomplete 120 0.0389864

As you can see in the table above, approximately 4 percent of the responses were from participants who were unable to complete all of the course activities as they desired. This may explain why the sentiment results are skewed so positively.

Discussion

Despite the short amount of text provided by the participants’ responses to the open-ended questions on the end of course surveys, there are still key insights to be gained that will aid refinements to our professional learning MOOC-Ed course on Teaching Remotely. In particular, some highlights from the analysis are:

  • Participants found content such as action plans, learning goals, unit 5, and unit 6 to be particularly valuable aspects of the course.
  • Participants expressed clear plans for applying course content to their own professional practice and are already doing so with practices such as establishing norms for their virtual classrooms, holding office hours and check ins, providing feedback, and using Google Classroom.
  • Course content may benefit from identifying redundant material in an effort to shorten time spent, including more participant peer interaction, or adding content that addressing remote teaching supports/resources for those with students who have special needs, such as students with disabilities.
  • On the whole, course ratings were very positive and the sentiments expressed by participants written responses agreed with these ratings.

Despite gaining these very useful insights from the end of course survey responses, we should consider that some insights may be missing due to the low response rates for those who were unable to complete the course. Finally, the results suggest that further text mining analysis may benefit from stemming the tokenized data.

The Author

Jennifer Houchins is a doctoral candidate in Learning Design and Technology at North Carolina State University. Her research examines students’ use of computational thinking and the effective use of instructional technology to deepen conceptual understanding in both formal and informal K-12 learning environments. She currently a graduate research assistant for the InfuseCS project, the Programmed Robotics in the School Makerspace (PRISM) project, and the Friday Institute’s Program Evaluation and Education Research (PEER) Group.

You can learn more about Jennifer and her work by visiting her website. You can also follow her on [@TooSweetGeek](https://twitter.com/TooSweetGeek).

Acknowledgements

This project uses techniques from Text Mining with R: A Tidy Approach by Julia Silge and David Robinson. Special thanks to our course instructor, Dr. Shaun Kellogg, for the sense of community created for this course as we all worked to learn R text mining techniques together.

End of Semester Feels

Bonus Content: This is Jenn. She is happy to be done with this crazy stressful year.

LS0tCnRpdGxlOiAiQSBDYXNlIFN0dWR5IG9mIFBhcnRpY2lwYW50IEZlZWRiYWNrIGZvciBhIFRlYWNoaW5nIFJlbW90ZWx5IFByb2Zlc3Npb25hbCBMZWFybmluZyBDb3Vyc2UiCmF1dGhvcjogIkplbm5pZmVyIEhvdWNoaW5zIgpkYXRlOiAnYHIgZm9ybWF0KFN5cy50aW1lKCksICIlQiAlZCwgJVkiKWAnCm91dHB1dDogCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgbGlnaHRib3g6IHRydWUKICAgIGdhbGxlcnk6IGZhbHNlCiAgICBoaWdobGlnaHQ6IGRlZmF1bHQKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgZW1iZWRfZm9udHM6IHRydWUKICAgIHVzZV9ib29rZG93bjogZmFsc2UKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCmBgYHtyIGxpYnJhcmllcywgaW5jbHVkZT1GQUxTRX0KIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImdhb3NwZWNpYWwvd29yZGNsb3VkMiIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpZHl0ZXh0KSAKbGlicmFyeShwbHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHdvcmRjbG91ZDIpIApsaWJyYXJ5KGh0bWx3aWRnZXRzKQpsaWJyYXJ5KHdlYnNob3QpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShyZW1vdGVzKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2d3b3JkY2xvdWQpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShmb250YXdlc29tZSkKbGlicmFyeSh2YWRlcikKc2V0LnNlZWQoMjAwNCkKYGBgClRoaXMgY2FzZSBzdHVkeSBzZXJ2ZXMgYXMgdGhlIGZpbmFsIHByb2plY3QgZm9yIHRoZSBFQ0kgNTg4IFRleHQgTWluaW5nIGluIEVkdWNhdGlvbiBjb3Vyc2Ugb2ZmZXJlZCBpbiBzcHJpbmcgMjAyMSBhdCBOb3J0aCBDYXJvbGluYSBTdGF0ZSBVbml2ZXJzaXR5LiBUaGlzIGNvdXJzZSBpcyBwYXJ0IG9mIHRoZSBMZWFybmluZyBBbmFseXRpY3MgQ2VydGlmaWNhdGUgUHJvZ3JhbS4KClRoZSBSbWFya2Rvd24gZmlsZSBjYW4gYmUgZG93bmxvYWRlZCBmcm9tIHRoZSBjb2RlIGZvbGRpbmcgY29udHJvbCBidXR0b24gaW4gdGhlIHVwcGVyIHJpZ2h0IGhhbmQgb2YgdGhpcyBwYWdlLiBUaGUgZnVsbCBSIFN0dWRpbyBwcm9qZWN0IGNhbiBiZSBhY2Nlc3MgdmlhIFt0aGlzIEdpdGh1YiByZXBvc2l0b3J5XShodHRwczovL2dpdGh1Yi5jb20vamVubmhvdWNoaW5zL1RlYWNoaW5nUmVtb3RlbHkpLiBIb3dldmVyLCBpdCBzaG91bGQgYmUgbm90ZWQgdGhhdCB0aGUgZGF0YSBmb3IgdGhpcyBwcm9qZWN0IGlzIG5vdCBpbmNsdWRlZCBiZWNhdXNlIGl0IHJlcXVpcmVzIHNwZWNpYWwgcGVybWlzc2lvbiBmb3Igc2hhcmluZy4KCiMgQ29udGV4dCBvZiB0aGlzIENhc2UgU3R1ZHkKClRoZSBkYXRhIHNvdXJjZSBmb3IgbXkgZmluYWwgcHJvamVjdCBjb25zaXN0cyBvZiB0aGUgZW5kIG9mIGNvdXJzZSBzdXJ2ZXkgcmVzcG9uc2VzIGZvciB0aGUgIlRlYWNoaW5nIFJlbW90ZWx5OiBBIFByYWN0aWNhbCBHdWlkZSIgMjAyMCBNT09DLUVkIGNvdXJzZSBvZmZlcmVkIGJ5IHRoZSBGcmlkYXkgSW5zdGl0dXRlIGZvciBFZHVjYXRpb25hbCBJbm5vdmF0aW9uLiBUaGlzIHByb2Zlc3Npb25hbCBsZWFybmluZyBjb3Vyc2Ugd2FzIG9mZmVyZWQgdG8gaGVscCBlZHVjYXRvcnMgYWRkcmVzcyB0aGUga2V5IGlzc3VlcyBvZiB0cmFuc2l0aW9uaW5nIHRvIEVtZXJnZW5jeSBSZW1vdGUgTGVhcm5pbmcgZHVlIHRvIHRoZSBDT1ZJRC0xOSBnbG9iYWwgcGFuZGVtaWMuIFRoZSBjb3Vyc2Ugb2JqZWN0aXZlcyBjb3ZlcmVkIGtleSBwcm9mZXNzaW9uYWwgZGV2ZWxvcG1lbnQgYXJlYXMgZm9yIHRlYWNoaW5nIHJlbW90ZWx5IHN1Y2ggYXMgZXN0YWJsaXNoaW5nIG5vcm1zIGZvciByZW1vdGUgbGVhcm5pbmcsIGJyaW5nIHNvY2lhbC1lbW90aW9uYWwgbGVhcm5pbmcgdG8gdGhlIHZpcnR1YWwgY2xhc3Nyb29tLCBtYWludGFpbmluZyBjb25uZWN0aW9ucyB3aXRoIHN0dWRlbnQgYW5kIGZhbWlsaWVzLCBkaWdpdGFsIGNvbnRlbnQgc2VsZWN0aW9uLCBzdXBwb3J0aW5nIGxlYXJuZXJzIHdpdGggc3BlY2lhbCBuZWVkcywgYW5kIHByb3ZpZGluZyBxdWFsaXR5IGZlZWRiYWNrLiBZb3UgY2FuIHJlYWQgbW9yZSBhYm91dCB0aGUgY291cnNlIG9uIHRoZSBGcmlkYXkgSW5zdGl0dXRlJ3MgW1Byb2Zlc3Npb25hbCBMZWFybmluZyBhbmQgQ29sbGFib3JhdGlvbiBFbnZpcm9ubWVudCBjb3Vyc2Ugc2l0ZV0oaHR0cHM6Ly9wbGFjZS5maS5uY3N1LmVkdS9sb2NhbC9jYXRhbG9nL2NvdXJzZS5waHA/aWQ9MjQmcmVmPTEpLgoKVGhlIHJhdyBkYXRhIGluY2x1ZGVzIDMsMDgwIGVuZCBvZiBjb3Vyc2Ugc3VydmV5IHJlc3BvbnNlcyB3aGVyZSBwYXJ0aWNpcGFudHMgcHJvdmlkZWQgdGhlaXIgcmF0aW5ncyBmb3Igb3ZlcmFsbCBlZmZlY3RpdmVuZXNzIG9mIHRoZSBjb3Vyc2UsIHRoZWlyIHBlcmNlaXZlZCBlZmZlY3RpdmVuZXNzIG9mIHBhcnRpY3VsYXIgYXNwZWN0cyBvZiB0aGUgY291cnNlLCB0aGVpciBlc3RpbWF0ZWQgbnVtYmVyIG9mIGhvdXJzIHNwZW50IGVuZ2FnZWQgaW4gdGhlIGNvdXJzZSBhY3Rpdml0aWVzLCBhbmQgdGhlaXIgcmF0aW5ncyBmb3IgaG93IGVmZmVjdGl2ZWx5IHRoZSBjb3Vyc2UgaW1wcm92ZWQgdGhlaXIgcHJhY3RpY2UuIFRoZSBtYWluIGZvY3VzIG9mIG15IHByb2plY3QgZm9yIHRoaXMgY291cnNlIHdpbGwgYmUgdGhlIG9wZW4tZW5kZWQsIHVuc3RydWN0dXJlZCB0ZXh0IHJlc3BvbnNlcyB0aGF0IHBhcnRpY2lwYW50cyBwcm92aWRlZCBpbiBhbnN3ZXIgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgotIFdoYXQgd2FzIHRoZSBtb3N0IHZhbHVhYmxlIGFzcGVjdCBvZiB0aGlzIGNvdXJzZSBpbiBzdXBwb3J0aW5nIHlvdXIgcGVyc29uYWwgb3IgcHJvZmVzc2lvbmFsIGxlYXJuaW5nIGdvYWxzPwoKLSBJbiB3aGF0IHdheXMsIGlmIGFueSwgZG8geW91IGFudGljaXBhdGUgYXBwbHlpbmcgdGhlIGtub3dsZWRnZSwgc2tpbGxzLCBhbmQvb3IgcmVzb3VyY2VzIHlvdSBhY3F1aXJlZCBmcm9tIHRoaXMgY291cnNlIHRvIHlvdXIgcHJvZmVzc2lvbmFsIHByYWN0aWNlPwoKLSBQbGVhc2UgZGVzY3JpYmUgYW55IGNoYW5nZXMgeW91IGhhdmUgbWFkZSB0byB5b3VyIHByYWN0aWNlLCBpbmNsdWRpbmcgaG93IHlvdSBoYXZlIGFwcGxpZWQgdGhlIGtub3dsZWRnZSwgc2tpbGxzLCBhbmQvb3IgcmVzb3VyY2VzIHlvdSBnYWluZWQgaW4gdGhpcyBjb3Vyc2UuCgotIFdoYXQgcmVjb21tZW5kYXRpb25zIGRvIHlvdSBoYXZlIGZvciBtYWtpbmcgdGhpcyBjb3Vyc2UgbW9yZSB2YWx1YWJsZSB0byBmdXR1cmUgcGFydGljaXBhbnRzIChlLmcuLCBvdGhlciByZXNvdXJjZXMsIGFkZGl0aW9uYWwgZmVhdHVyZXMsIGFjdGl2aXRpZXMsIGV0Yy4pPyBQbGVhc2UgZXhwbGFpbi4KCiMjIEd1aWRpbmcgUXVlc3Rpb25zCgpJIGFtIGludGVyZXN0ZWQgaW4gdGhpcyBkYXRhL2NvbnRleHQgYmVjYXVzZSBJIGFtIGhlYXZpbHkgaW52b2x2ZWQgaW4gZGV2ZWxvcGluZyBlZHVjYXRvciBwcm9mZXNzaW9uYWwgZGV2ZWxvcG1lbnQgYW5kIHRoaXMgYW5hbHlzaXMgbWF5IGhlbHAgZ3VpZGUgc3VjaCBkZXZlbG9wbWVudC4gSW4gcGFydGljdWxhciwgbXkgZ3VpZGluZyBxdWVzdGlvbnMgZm9yIHRoaXMgY2FzZSBzdHVkeSB3aWxsIGJlOgoKMS4gV2hhdCBhc3BlY3RzIG9mIHRoZSBUZWFjaGluZyBSZW1vdGVseSBwcm9mZXNzaW9uYWwgZGV2ZWxvcG1lbnQgY291cnNlIGRvIHBhcnRpY2lwYW50cyBmaW5kIG1vc3QgdmFsdWFibGU/CgoyLiBXaGF0IGNoYW5nZXMsIGlmIGFueSwgYXJlIGJlaW5nIG1hZGUgdG8gcGFydGljaXBhbnRzJyBwcmFjdGljZSBhcyBhIHJlc3VsdCBvZiB0aGVpciBwYXJ0aWNpcGF0aW9uIGluIHRoaXMgY291cnNlPwoKMy4gSWYgcGFydGljaXBhbnRzIGZvdW5kIHRoZSBjb3Vyc2UgdG8gYmUgaW5lZmZlY3RpdmUsIHdoYXQgc3BlY2lmaWMgcmVjb21tZW5kYXRpb25zIGhhdmUgdGhleSBtYWRlIGZvciBpdHMgaW1wcm92ZW1lbnQ/Cgo0LiBIb3cgZG8gdGhlIHNlbnRpbWVudHMgb2YgcGFydGljaXBhbnRzJyBvcGVuLWVuZGVkIHJlc3BvbnNlcyBjb21wYXJlIHRvIHRoZWlyIHJhdGluZ3Mgb2YgdGhlIGNvdXJzZSdzIG92ZXJhbGwgZWZmZWN0aXZlbmVzcz8KCiMjIFRhcmdldCBBdWRpZW5jZQoKTXkgdGFyZ2V0IGF1ZGllbmNlIGlzIGFueSBvdGhlciByZXNlYXJjaGVyIG9yIHRlYWNoZXIgZWR1Y2F0b3Igd2hvLCBsaWtlIG15c2VsZiwgaXMgaW50ZXJlc3RlZCBpbiBtYWtpbmcgaW1wcm92ZW1lbnRzIHRvIHRoZWlyIG93biBwcm9mZXNzaW9uYWwgZGV2ZWxvcG1lbnQgb2ZmZXJpbmdzLiBJIGhvcGUgdGhhdCB0aGUgYW5hbHlzaXMgd2lsbCBoZWxwIGlkZW50aWZ5ICJiZXN0IHByYWN0aWNlcyIgYnkgZXhhbWluaW5nIHRoZSBjb21wb25lbnRzIG9mIHByb2Zlc3Npb25hbCBsZWFybmluZyB0aGF0IGFyZSBtb3N0IHZhbHVhYmxlIGFzIHdlbGwgYXMgc3BlY2lmaWMgYXJlYXMgdGhhdCBjb3VsZCBiZSB0YXJnZXRlZCBmb3IgaW1wcm92ZW1lbnQuCgojIyBMaW1pdGF0aW9ucyBvZiB0aGlzIENhc2UgU3R1ZHkKCkJlZm9yZSBkaXZpbmcgaW50byB0aGUgYW5hbHlzaXMgb2YgdGhpcyBkYXRhLCBpdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHJlc3BvbnNlcyB0byB0aGUgZW5kIG9mIGNvdXJzZSBzdXJ2ZXkgd2VyZSB2b2x1bnRhcnkuIFRoZXJlZm9yZSwgaXQgaXMgcG9zc2libGUgdGhhdCB0aG9zZSBwYXJ0aWNpcGFudHMgd2hvIGRpZCBub3QgY29tcGxldGUgYWxsIG9mIHRoZSBhY3Rpdml0aWVzIG9yIHRoYXQgZm91bmQgdGhlIGNvdXJzZSB0byBiZSBpbmVmZmVjdGl2ZSBkaWQgbm90IHJlc3BvbmQgdG8gdGhlIGVuZCBvZiBjb3Vyc2Ugc3VydmV5LiBFeGFtaW5pbmcgdGhlIGRhdGEgZG9lcyBzaG93IHRoYXQgdGhlIHJhdGluZ3MgZm9yIG92ZXJhbGwgZWZmZWN0aXZlbmVzcyBvZiB0aGUgY291cnNlIGlzIHNrZXdlZCB2ZXJ5IHBvc2l0aXZlbHkgd2hpY2ggY29uZmlybXMgdGhhdCBhIGtleSBsaW1pdGF0aW9uIGZvciB0aGlzIGNhc2Ugc3R1ZHkgbGllcyBpbiB0aGUgcmVzcG9uc2UgcmF0ZXMgZm9yIHRob3NlIHBhcnRpY2lwYW50cyB3aG8gb25seSBjb21wbGV0ZWQgYSBwb3J0aW9uIG9mIHRoZSBjb3Vyc2Ugb3Igd2VyZSBkaXNzYXRpc2ZpZWQgd2l0aCB0aGUgY291cnNlIGNvbnRlbnQgaW4gc29tZSBtYW5uZXIuICAKCiMgRW5kIG9mIENvdXJzZSBTdXJ2ZXkgQW5hbHlzaXMKCkluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMsIHRoZSBwcm9jZXNzZXMgdXNlZCB0byBhbmFseXplIHRoZSBlbmQgb2YgY291cnNlIHN1cnZleSBkYXRhIGFyZSBkZXNjcmliZWQgYW5kIGZpbmRpbmdzIGFyZSBwcmVzZW50ZWQuCgojIyBEYXRhIFdyYW5nbGluZwoKTXkgaW5pdGlhbCBwcmUtcHJvY2Vzc2luZyBvZiB0aGUgZGF0YSBiZWdhbiB3aXRoIHJlbW92aW5nIHNvbWUgSFRNTCBmb3JtYXR0aW5nIHRoYXQgYXBwZWFycyBpbiB0ZXh0IHJlc3BvbnNlcyBhbmQgc2V0dGluZyBjb2x1bW4gbmFtZXMgdGhhdCBhcmUgbW9yZSByZWFkYWJsZSB0aGFuIHRob3NlIGFzc2lnbmVkIGJ5IHRoZSBzdXJ2ZXkgc3lzdGVtLiBJIGNob3NlIG5vdCB0byBvbWl0ICoqX05BXyoqIHZhbHVlcyBhdCB0aGlzIHBvaW50IHNpbXBseSBiZWNhdXNlIHRoZXJlIHdhcyBhdCBsZWFzdCBvbmUgaW4gZXZlcnkgcmVzcG9uc2UgYW5kIHRoYXQgcmVzdWx0ZWQgaW4gbm8gZGF0YSBsZWZ0IHRvIGFuYWx5emUhIEluc3RlYWQsIEkgb21pdCB0aGUgKipfTkFfKiogdmFsdWVzIGF0IGFwcHJvcHJpYXRlIHBvaW50cyB0aHJvdWdob3V0IG15IGFuYWx5c2lzLiBBZGRpdGlvbmFsbHksIHNpbmNlIHNvbWUgY3Vyc29yeSBleHBsb3JhdGlvbiBvZiB0aGUgZGF0YSBzaG93ZWQgdGhhdCBwYXJ0aWNpcGFudHMgbWFkZSBtZW50aW9uIG9mIHNwZWNpZmljIHVuaXQgbnVtYmVycywgSSBhbHNvIGNob3NlIG5vdCB0byByZW1vdmUgbnVtYmVycy9kaWdpdHMgZnJvbSB0aGUgdGV4dCByZXNwb25zZXMgd2hlbiBJIHByZS1wcm9jZXNzZWQgdGhlIGRhdGEuIFRoZSBmb2xsb3dpbmcgc2hvd3MgdGhlIGNsZWFuIGNvbHVtbiBuYW1lcyBhbmQgYSBnbGltcHNlIG9mIHRoZSBkYXRhIGNvbnRhaW5lZCBpbiB0aGUgZW5kIG9mIGNvdXJzZSBzdXJ2ZXkgcmVzcG9uc2VzLgoKYGBge3IgZ2V0LWRhdGEsIGNhY2hlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFfQplb2Nfc3VydmV5X2RhdGEgPC0gcmVhZF9jc3YoImRhdGEvZW9jX3N1cnZleWRhdGFfd3JhbmdsZWRfZ3JvdXBlZC5jc3YiKSAlPiUgCiAgc2VsZWN0KHJlc3BvbnNlLAogICAgICAgICBFZmZlY3RpdmVuZXNzUmF0aW5nLAogICAgICAgICBJbnRyb0Rpc2N1c3Npb25SYXRpbmcsCiAgICAgICAgIENvdXJzZUNvbnRlbnRSYXRpbmcsCiAgICAgICAgIFB1dHRpbmdJdFRvZ2V0aGVyUmF0aW5nLAogICAgICAgICBBY3Rpb25QbGFuUmF0aW5nLAogICAgICAgICBSZXNvdXJjZXNSYXRpbmcsCiAgICAgICAgIE1vc3RWYWx1YWJsZUFzcGVjdHMsCiAgICAgICAgIEltcHJvdmVtZW50RXN0YWJsaXNoaW5nTm9ybXMsCiAgICAgICAgIEltcHJvdmVtZW50QnJpbmdpbmdTRUwsCiAgICAgICAgIEltcHJvdmVtZW50TWFpbnRhaW5pbmdDb25uZWN0aW9uLAogICAgICAgICBJbXByb3ZlbWVudFNlbGVjdERpZ1Jlc291cmNlcywKICAgICAgICAgSW1wcm92ZW1lbnRTdXBwb3J0U3BlY2lhbFBvcCwKICAgICAgICAgSW1wcm92ZW1lbnRQcm92aWRpbmdGZWVkYmFjaywKICAgICAgICAgUG9zaXRpdmVDaGFuZ2VzRWZmZWN0aXZlbmVzcywKICAgICAgICAgSGFzQXR0ZW1wdGVkQ2hhbmdlcywKICAgICAgICAgQW50aWNpcGF0ZWRBcHBsaWNhdGlvblByYWN0aWNlLAogICAgICAgICBDaGFuZ2VzVG9QcmFjdGljZSwKICAgICAgICAgQ291cnNlUmVjb21tZW5kYXRpb25zLAogICAgICAgICBEZXNpcmVkQWN0aXZpdHlDb21wbGV0aW9uLAogICAgICAgICBDb3Vyc2VIb3Vyc0VzdGltYXRlLAogICAgICAgICB0ZXh0KSAlPiUgCiAgbXV0YXRlKENvdXJzZUhvdXJzRXN0aW1hdGUgPSBhcy5mYWN0b3IoQ291cnNlSG91cnNFc3RpbWF0ZSkpICU+JSAKICBtdXRhdGUoQ291cnNlQ29tcGxldGlvbiA9IGFzLmZhY3RvcihpZmVsc2UoRGVzaXJlZEFjdGl2aXR5Q29tcGxldGlvbiA9PSAwLCAiaW5jb21wbGV0ZSIsICJjb21wbGV0ZSIpKSkgJT4lIAogIGZpbHRlcihyZXNwb25zZSAhPSA4NzY4NCwKICAgICAgICAgcmVzcG9uc2UgIT0gODk0MTcpCmBgYAoKYGBge3Igc25lYWtwZWFrfQpnbGltcHNlKGVvY19zdXJ2ZXlfZGF0YSkKYGBgCgpBcyB5b3Ugd2lsbCBub3RpY2UsIHR3byBvZiB0aGUgc3VydmV5IHJlc3BvbnNlcyB3ZXJlIGRpc2NhcmRlZCBkdWUgdG8gY29ycnVwdGVkIGNoYXJhY3RlciBlbmNvZGluZ3Mgd2l0aGluIHRoZSB0ZXh0IHJlc3BvbnNlcy4gSSBiZWxpZXZlIHRoaXMgbWF5IGhhdmUgYmVlbiBkdWUgdG8gcGFydGljaXBhbnRzIGNvcHlpbmcgYW5kIHBhc3RpbmcgbWF0ZXJpYWwgaW50byB0aGVpciByZXNwb25zZXMuIFRoZSBmb2xsb3dpbmcgc2VjdGlvbnMgcHJlc2VudCBteSBhbmFseXNpcyBvZiB0aGUgVGVhY2hpbmcgUmVtb3RlbHkgTU9PQy1FRCBlbmQgb2YgY291cnNlIHN1cnZleSByZXNwb25zZXMgYXJyYW5nZWQgYnkgdGhlIGd1aWRpbmcgcXVlc3Rpb25zIHRoYXQgZnJhbWUgdGhlIGNhc2Ugc3R1ZHkuCgojIyBNb3N0IFZhbHVhYmxlIEFzcGVjdHMKClRoZSBmaXJzdCBndWlkaW5nIHF1ZXN0aW9uIGZvciBteSBhbmFseXNpcyBpczoKCioqV2hhdCBhc3BlY3RzIG9mIHRoZSBUZWFjaGluZyBSZW1vdGVseSBwcm9mZXNzaW9uYWwgZGV2ZWxvcG1lbnQgY291cnNlIGRvIHBhcnRpY2lwYW50cyBmaW5kIG1vc3QgdmFsdWFibGU/KioKCkJhc2VkIG9uIHRoZSBuYXR1cmUgb2YgdGhlIHJlc3BvbnNlcywgd2hpY2ggYXJlIHByZXR0eSBzaG9ydCwgdGhlIHRleHQgd2FzIHRva2VuaXplZCBhbmQgc3RvcCB3b3JkcyB3ZXJlIHJlbW92ZWQuIFNpbmNlIHRoZSByZXNwb25zZXMgY29udGFpbmVkIHNvbWUgSFRNTCBmcm9tIHRoZSBzdXJ2ZXkgc3lzdGVtLCBjdXN0b20gc3RvcCB3b3JkcyB3ZXJlIGFsc28gZW1wbG95ZWQgZm9yIHRoZSB0b2tlbml6YXRpb24gcHJvY2VzcyAoZS5nLiwgIm5ic3AiIG9yICJhbXAiKS4gSXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgc29tZSBvZiB0aGUgTU9PQy1FZCBwYXJ0aWNpcGFudHMgY2hvc2Ugbm90IHRvIHJlc3BvbmQgdG8gdGhlIHN1cnZleSBxdWVzdGlvbjogIldoYXQgd2FzIHRoZSBtb3N0IHZhbHVhYmxlIGFzcGVjdCBvZiB0aGlzIGNvdXJzZSBpbiBzdXBwb3J0aW5nIHlvdXIgcGVyc29uYWwgb3IgcHJvZmVzc2lvbmFsIGxlYXJuaW5nIGdvYWxzPyIgVGhlcmVmb3JlLCBJIGhhZCB0byBkbyBzb21lIGZ1cnRoZXIgcHJlLXByb2Nlc3NpbmcgYXQgdGhpcyBzdGFnZSBhbmQgb21pdCBhbnkgKipfTkFfKiogdmFsdWVzIHRoYXQgd2VyZSBsdXJraW5nIGluIHRoZSBkYXRhLgoKYGBge3IgYXNwZWN0cywgY2FjaGU9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZW9jX2FzcGVjdHMgPC0gZW9jX3N1cnZleV9kYXRhICU+JQogIHNlbGVjdChyZXNwb25zZSwgTW9zdFZhbHVhYmxlQXNwZWN0cykgJT4lCiAgc2xpY2UoLTEsIC0yKSAlPiUKICBuYS5vbWl0KCkKCmVvY19hc3BlY3RzICU+JSAKICBzZWxlY3QoTW9zdFZhbHVhYmxlQXNwZWN0cykKYGBgCgpDdXN0b20gc3RvcCB3b3JkcyB3ZXJlIGVtcGxveWVkIGZvciB0aGUgbGVmdG92ZXIgSFRNTCB0aGF0IGNyZXB0IGludG8gdGhlIHJlc3BvbnNlcyAoZS5nLiwgbmJzcCBvciBhbXApIGFuZCBmb3Igd29yZHMgdGhhdCB3ZXJlIHNpbXBseSBhIHJlc3RhdGluZyBvZiB0aGUgc3VydmV5IHByb21wdCAoZS5nLiwgdmFsdWFibGUgYW5kIGFzcGVjdCkgYXMgcGFydCBvZiB0aGUgcmVzcG9uc2UuCgpgYGB7ciB0b2tlbml6ZSwgY2FjaGU9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KY3VzdG9tX3N0b3AgPC0gZGF0YS5mcmFtZSgid29yZCIgPSBjKCJuYnNwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhbXAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5BIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOL0EiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk4vYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYXNwZWN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidmFsdWFibGUiKSkKCmVvY190aWR5X2FzcGVjdHMgPC0gZW9jX2FzcGVjdHMgJT4lIAogIHVubmVzdF90b2tlbnMod29yZCwgTW9zdFZhbHVhYmxlQXNwZWN0cykgJT4lCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpICU+JSAKICBhbnRpX2pvaW4oY3VzdG9tX3N0b3ApCmBgYAoKQmVsb3cgeW91IGNhbiBzZWUgdGhlIHdvcmRzIHRoYXQgYXBwZWFyIGluIHRoZSBxdWVzdGlvbiByZXNwb25zZXMgYXQgbGVhc3QgMTUwIHRpbWVzLiBSZXNvdXJjZXMgaXMgYXQgdGhlIHRvcCBvZiB0aGUgbGlzdCwgYnV0IGlnbm9yaW5nIHNvbWUgd29yZHMgbGlrZSBoZWxwZWQgb3IgaGVscGZ1bCB0aGVyZSBhcmUgb3RoZXJzIHRoYXQgc3RhbmQgb3V0IHN1Y2ggYXMgaWRlYXMsIGxpbmtzLCB2aWRlb3MsIGFydGljbGVzLCBmZWVkYmFjaywgYW5kIGRpc2N1c3Npb24uCgpgYGB7ciB0b2tlbnBsb3R9CmVvY190aWR5X2FzcGVjdHMgJT4lIAogIGRwbHlyOjpjb3VudCh3b3JkLCBzb3J0ID0gVFJVRSkgJT4lIAogIGZpbHRlcihuID4gMTUwKSAlPiUgCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUgCiAgZ2dwbG90KGFlcyhuLCB3b3JkKSkgKyAKICB0aGVtZV9taW5pbWFsKCkgKwogIGdlb21fY29sKGZpbGw9IiM3QjBEMUUiKSArIAogIGxhYnMoeSA9IE5VTEwpCmBgYAoKYGBge3IgdG9rZW4tY291bnRzLCBjYWNoZT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQp0b2tlbl9jb3VudHNfYXNwZWN0cyA8LSAgZW9jX3RpZHlfYXNwZWN0cyAlPiUgCiAgZHBseXI6OmNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKQoKZW9jX3dvcmRfY291bnRzX2FzcGVjdHMgPC0gZW9jX3RpZHlfYXNwZWN0cyAlPiUKICBkcGx5cjo6Y291bnQocmVzcG9uc2UsIHdvcmQsIHNvcnQgPSBUUlVFKSAlPiUKICBtdXRhdGUocHJvcG9ydGlvbiA9IG4gLyBzdW0obikpCgplb2Nfd29yZF9jb3VudHNfYXNwZWN0cwoKdG90YWxfd29yZHMgPC0gZW9jX3dvcmRfY291bnRzX2FzcGVjdHMgJT4lCiAgZ3JvdXBfYnkocmVzcG9uc2UpICU+JSAKICBzdW1tYXJpc2UodG90YWwgPSBzdW0obikpCgplb2Nfd29yZF90b3RhbHMgPC0gbGVmdF9qb2luKGVvY193b3JkX2NvdW50c19hc3BlY3RzLCB0b3RhbF93b3JkcywgYnkgPSBjaGFyYWN0ZXIoKSkKCmVvY193b3JkX3RvdGFscwpgYGAKCkl0IHdhcyBhdCB0aGlzIHBvaW50IHRoYXQgSSBkZWNpZGVkIHRvIGV4YW1pbmUgYmlncmFtcyBmb3IgdGhpcyBxdWVzdGlvbi4gQXMgeW91IGNhbiBzZWUgaW4gdGhlIGJhciBjaGFydCwgc29tZSBvZiB0aGUgbW9zdCBmcmVxdWVudGx5IHVzZWQgd29yZHMgYXJlIHBsYW4gYW5kIHVuaXQuIFRoZXNlIG9mdGVuIGFwcGVhciBpbiB0aGUgcmVzcG9uc2VzIGFzIHBhcnQgb2YgcGhyYXNlcywgc3VjaCBhcyAiYWN0aW9uIHBsYW4iIG9yICJ1bml0IDMiIGFuZCBJIGhvcGVkIHRvIGNhcHR1cmUgbW9yZSBzcGVjaWZpYyB2YWx1YWJsZSBhc3BlY3RzIG9mIHRoZSBNT09DLUVkIHN1Y2ggYXMgdGhlc2UgaWYgYXQgYWxsIHBvc3NpYmxlLgoKYGBge3IgYmlncmFtcy1jb3VudHMsIGNhY2hlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmVvY19hc3BlY3RzX2JpZ3JhbXMgPC0gZW9jX2FzcGVjdHMgJT4lCiAgdW5uZXN0X25ncmFtcyhiaWdyYW0sIE1vc3RWYWx1YWJsZUFzcGVjdHMsIG4gPSAyLCB0b19sb3dlciA9IFRSVUUpIAoKZW9jX3NlcGFyYXRlZF9hc3BlY3RzIDwtIGVvY19hc3BlY3RzX2JpZ3JhbXMgJT4lICAKICBzZXBhcmF0ZShiaWdyYW0sIGludG8gPSBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpICU+JSAKICBuYS5vbWl0KCkKCmVvY191bml0ZWRfYXNwZWN0cyA8LSBlb2Nfc2VwYXJhdGVkX2FzcGVjdHMgJT4lCiAgZmlsdGVyKCEod29yZDEgJWluJSBzdG9wX3dvcmRzJHdvcmQpLCAKICAgICAgICAgISh3b3JkMiAlaW4lIHN0b3Bfd29yZHMkd29yZCkpICU+JSAgCiAgZmlsdGVyKCEod29yZDEgJWluJSBjdXN0b21fc3RvcCR3b3JkKSwgCiAgICAgICAgICEod29yZDIgJWluJSBjdXN0b21fc3RvcCR3b3JkKSkgJT4lCiAgdW5pdGUoYmlncmFtLCBjKHdvcmQxLCB3b3JkMiksIHNlcCA9ICIgIikKCmJpZ3JhbV9jb3VudHNfYXNwZWN0cyA8LSBlb2NfdW5pdGVkX2FzcGVjdHMgJT4lCiAgZHBseXI6OmNvdW50KGJpZ3JhbSwgc29ydCA9IFRSVUUpICU+JQogIHRvcF9uKDI1KQoKYGBgCgpBcyB5b3UgY2FuIHNlZSBmcm9tIHRoZSB3b3JkIGNsb3VkIGJlbG93LCBleGFtaW5pbmcgdGhlIGJpZ3JhbXMgd2FzIGFjdHVhbGx5IGZydWl0ZnVsLiBJdCByZXZlYWxlZCB0aGF0IGFzcGVjdHMgbGlrZSAiYWN0aW9uIHBsYW4iLCAibGVhcm5pbmcgZ29hbHMiLCAidW5pdCA1IiwgYW5kICJ1bml0IDYiIHdlcmUgbWVudGlvbmVkIHF1aXRlIGZyZXF1ZW50bHkgYnkgdGhvc2Ugd2hvIHJlc3BvbmRlZCB0byB0aGUgZW5kIG9mIGNvdXJzZSBzdXJ2ZXkuIEl0IGFsc28gcmV2ZWFsZWQgb3RoZXIga2V5IGNvbnRlbnQgbGlrZSAic29jaWFsIGVtb3Rpb25hbCIsICJzcGVjaWFsIGVkdWNhdGlvbiIsICJlc3RhYmxpc2hpbmcgbm9ybXMiIGFuZCAiZGlnaXRhbCBjaXRpemVuc2hpcCIuCgpgYGB7ciB3b3JkY2xvdWQtYXNwZWN0cywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQp3b3JkY2xvdWQyKGJpZ3JhbV9jb3VudHNfYXNwZWN0cywgc2l6ZSA9IDIsIHNoYXBlPSdjaXJjbGUnLCBjb2xvcj0nIzdCMEQxRScpCmBgYAoKIyMgQ2hhbmdlcyB0byBQcmFjdGljZQoKVGhlIHNlY29uZCBndWlkaW5nIHF1ZXN0aW9uIGZvciBteSBhbmFseXNpcyBpczoKCioqV2hhdCBjaGFuZ2VzLCBpZiBhbnksIGFyZSBiZWluZyBtYWRlIHRvIHBhcnRpY2lwYW50cycgcHJhY3RpY2UgYXMgYSByZXN1bHQgb2YgdGhlaXIgcGFydGljaXBhdGlvbiBpbiB0aGlzIGNvdXJzZT8qKgoKQW5zd2VyaW5nIHRoaXMgcXVlc3Rpb24gZm9jdXNlcyBpbiBvbiB0aGUgZm9sbG93aW5nIHR3byBzdXJ2ZXkgcXVlc3Rpb25zOgoKLSBJbiB3aGF0IHdheXMsIGlmIGFueSwgZG8geW91IGFudGljaXBhdGUgYXBwbHlpbmcgdGhlIGtub3dsZWRnZSwgc2tpbGxzLCBhbmQvb3IgcmVzb3VyY2VzIHlvdSBhY3F1aXJlZCBmcm9tIHRoaXMgY291cnNlIHRvIHlvdXIgcHJvZmVzc2lvbmFsIHByYWN0aWNlPwotIFBsZWFzZSBkZXNjcmliZSBhbnkgY2hhbmdlcyB5b3UgaGF2ZSBtYWRlIHRvIHlvdXIgcHJhY3RpY2UsIGluY2x1ZGluZyBob3cgeW91IGhhdmUgYXBwbGllZCB0aGUga25vd2xlZGdlLCBza2lsbHMsIGFuZC9vciByZXNvdXJjZXMgeW91IGdhaW5lZCBpbiB0aGlzIGNvdXJzZS4KClJlc3BvbnNlcyB0byB0aGVzZSBxdWVzdGlvbnMgd2VyZSBjYXB0dXJlZCBpbiB0aGUgZGF0YWZyYW1lIGNvbHVtbnMgY2FsbGVkICoqQW50aWNpcGF0ZWRBcHBsaWNhdGlvblByYWN0aWNlKiogYW5kICoqQ2hhbmdlc1RvUHJhY3RpY2UqKi4gTGV0J3MgZmlyc3QgZm9jdXMgb24gdGhlIGNoYW5nZXMgdGhhdCBwYXJ0aWNpcGFudHMgYW50aWNpcGF0ZWQgbWFraW5nIHRvIHRoZWlyIHByYWN0aWNlLiBXZSdsbCBqdXN0IGdyYWIgdGhlICoqQW50aWNpcGF0ZWRBcHBsaWNhdGlvblByYWN0aWNlKiogY29sdW1uIGZyb20gb3VyIGRhdGFmcmFtZSBhbmQgZG8gc29tZSBmdXJ0aGVyIHByZS1wcm9jZXNzaW5nIGJ5IHN0cmlwcGluZyBvdXQgbGluZ2VyaW5nIEhUTUwgdGFncyBhbmQgcmVzcG9uc2VzIHdoZXJlIHRoZSBwYXJ0aWNpcGFudHMganVzdCB3cm90ZSBzb21lIHZhcmlhbnQgb2YgIk4vQS4iCgpgYGB7ciBhbnRpY2lwYXRlZC1hcHAsIGNhY2hlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmFudGljaXBhdGVkX2NoYW5nZXMgPC0gZW9jX3N1cnZleV9kYXRhICU+JQogIHNlbGVjdChyZXNwb25zZSwgQW50aWNpcGF0ZWRBcHBsaWNhdGlvblByYWN0aWNlKSAlPiUKICBtdXRhdGUoQW50aWNpcGF0ZWRBcHBsaWNhdGlvblByYWN0aWNlID0gZ3N1YignJm5ic3A7JywgJyAnLCBBbnRpY2lwYXRlZEFwcGxpY2F0aW9uUHJhY3RpY2UpKSAlPiUgCiAgbXV0YXRlKEFudGljaXBhdGVkQXBwbGljYXRpb25QcmFjdGljZSA9IGdzdWIoJyZhbXA7JywgJyAnLCBBbnRpY2lwYXRlZEFwcGxpY2F0aW9uUHJhY3RpY2UpKSAlPiUKICBzbGljZSgtMSwgLTIpICU+JQogIG5hLm9taXQoKSAlPiUgCiAgZmlsdGVyKEFudGljaXBhdGVkQXBwbGljYXRpb25QcmFjdGljZSAhPSAnTi9BJykKCmFudGljaXBhdGVkX2NoYW5nZXMgJT4lIAogIHNlbGVjdChBbnRpY2lwYXRlZEFwcGxpY2F0aW9uUHJhY3RpY2UpCmBgYAoKVGhlcmUgYXJlIG9ubHkgNzggcmVzcG9uc2VzIHRvIHRoaXMgc3VydmV5IHF1ZXN0aW9uIGFib3V0IGFudGljaXBhdGVkIGNoYW5nZXMgdG8gcGFydGljaXBhbnRzJyBwcm9mZXNzaW9uYWwgcHJhY3RpY2UsIHNvIHdlJ2xsIGp1c3QgZ3JhYiBhIHNhbXBsaW5nIG9mIHRob3NlIHRvIGV4YW1pbmUgdGhlbSBmb3IgYW55IHBhdHRlcm5zLiBJbiBwYXJ0aWN1bGFyLCB3ZSB3aWxsIHRhcmdldCB0aGUgcmVzcG9uc2VzIHRoYXQgc3BlY2lmaWNhbGx5IG1lbnRpb24gYSBwYXJ0aWNpcGFudCdzICJwbGFuIiBhbmQgZ3JhYiB0ZW4gb2YgdGhvc2UgdG8gcmVhZCBtb3JlIGNsb3NlbHkuCgpgYGB7ciBhbnRpY2lwYXRpb24tc25hcHNob3QsIGNhY2hlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmNoYW5nZXNfcXVvdGVzIDwtIGFudGljaXBhdGVkX2NoYW5nZXMgJT4lCiAgc2VsZWN0KEFudGljaXBhdGVkQXBwbGljYXRpb25QcmFjdGljZSkgJT4lIAogIGZpbHRlcihncmVwbCgncGxhbicsIEFudGljaXBhdGVkQXBwbGljYXRpb25QcmFjdGljZSkpCgpzYW1wbGVfY2hhbmdlcyA8LSBzYW1wbGVfbihjaGFuZ2VzX3F1b3RlcywgMTApCmBgYAoKYGBge3Igc2hvdy1hbnRpY2lwYXRlZCwgY2FjaGU9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Ka2FibGUoc2FtcGxlX2NoYW5nZXMpCmBgYAoKRXZlbiB3aXRoIGp1c3QgdGhpcyBoYW5kZnVsIG9mIHJlc3BvbnNlcywgd2UgY2FuIHNlZSB0aGF0IHBhcnRpY2lwYW50cyBwbGFuIHRvOiAxKSBlc3RhYmxpc2ggbm9ybXMgYW5kIHByb3ZpZGUgc29jaWFsLWVtb3Rpb25hbCBsZWFybmluZyAoU0VMKSB0aHJvdWdoIHJlbGF0aW9uc2hpcC1idWlsZGluZyBhY3Rpdml0aWVzIGluIHRoZWlyIHZpcnR1YWwgY2xhc3Nyb29tczsgMikgbWFpbnRhaW4gZWZmZWN0aXZlIGNvbW11bmljYXRpb24gd2l0aCBzdHVkZW50cyBhbmQgdGhlaXIgZmFtaWxpZXM7IDMpIGFuZCBzaGFyZSB0aGUgY29udGVudCB0aGV5IGxlYXJuZWQgd2l0aCBjb2xsZWFndWVzLiBTaW5jZSBzb21lIG9mIHRoZXNlIGFyZSBsZWFybmluZyBvYmplY3RpdmVzIGZvciB0aGUgTU9PQy1FZCBUZWFjaGluZyBSZW1vdGVseSBjb3Vyc2UsIHRoZXNlIHJlc3BvbnNlcyBhcHBlYXIgdG8gaW5kaWNhdGUgdGhhdCBwYXJ0aWNpcGFudHMgY2FuIGVudmlzaW9uIGhvdyB0aGUgY291cnNlIGNvbnRlbnQgYWxpZ25zIHdpdGggYW5kIGhvdyB0aGV5IGNhbiBhcHBseSBpdCB0byB0aGVpciBvd24gcHJvZmVzc2lvbmFsIHByYWN0aWNlLgoKTm93IHRoYXQgd2UgaGF2ZSBzZWVuIGhvdyBwYXJ0aWNpcGFudHMgYW50aWNpcGF0ZSBhcHBseWluZyB0aGUgY291cnNlIGNvbnRlbnQsIGxldCdzIGV4YW1pbmUgdGhlIGNoYW5nZXMgdGhleSBpbmRpY2F0ZSB0aGV5IGhhdmUgYWxyZWFkeSBtYWRlIHRvIHRoZWlyIHByYWN0aWNlLiBJbiB0aGlzIGNhc2UsIHdlJ2xsIGNvbmNlbnRyYXRlIG9uIHRoZSAqKkNoYW5nZXNUb1ByYWN0aWNlKiogY29sdW1uIG9mIG91ciBkYXRhZnJhbWUuCgpgYGB7ciBwcmFjdGljZS1jaGFuZ2VzLCBjYWNoZT1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcmFjdGljZV9jaGFuZ2VzIDwtIGVvY19zdXJ2ZXlfZGF0YSAlPiUKICBzZWxlY3QocmVzcG9uc2UsIENoYW5nZXNUb1ByYWN0aWNlKSAlPiUKICBtdXRhdGUoQ2hhbmdlc1RvUHJhY3RpY2UgPSBnc3ViKCcmbmJzcDsnLCAnICcsIENoYW5nZXNUb1ByYWN0aWNlKSkgJT4lIAogIG11dGF0ZShDaGFuZ2VzVG9QcmFjdGljZSA9IGdzdWIoJyZhbXA7JywgJyAnLCBDaGFuZ2VzVG9QcmFjdGljZSkpICU+JQogIHNsaWNlKC0xLCAtMikgJT4lCiAgbmEub21pdCgpICU+JSAKICBmaWx0ZXIoQ2hhbmdlc1RvUHJhY3RpY2UgIT0gJ04vQScpCgpwcmFjdGljZV9jaGFuZ2VzICU+JSAKICBzZWxlY3QoQ2hhbmdlc1RvUHJhY3RpY2UpCmBgYAoKTG9va2luZyBhdCB0aGUgdG9rZW5pemVkIHJlc3BvbnNlcyB0byB0aGlzIHN1cnZleSBxdWVzdGlvbiByZXZlYWxzIHRoYXQgcGFydGljaXBhbnRzIHdpbGwgZm9jdXMgY2hhbmdlcyB0byB0aGVpciBwcmFjdGljZSBvbiBzdHVkZW50cywgcmVzb3VyY2VzLCBmZWVkYmFjaywgbm9ybXMsIGFuZCBTRUwuIFRoZXkgYWxzbyBmcmVxdWVudGx5IG1lbnRpb24gdG9vbHMsIHBsYW5uaW5nLCBhc3Nlc3NtZW50LCBhbmQgY29tbXVuaWNhdGlvbi4gCgpgYGB7ciBjaGFuZ2VzLXRva2VucywgY2FjaGU9VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZW9jX3RpZHlfY2hhbmdlcyA8LSBwcmFjdGljZV9jaGFuZ2VzICU+JSAKICB1bm5lc3RfdG9rZW5zKHdvcmQsIENoYW5nZXNUb1ByYWN0aWNlKSAlPiUKICBhbnRpX2pvaW4oc3RvcF93b3JkcykKCmVvY190aWR5X2NoYW5nZXMgJT4lIAogIGRwbHlyOjpjb3VudCh3b3JkLCBzb3J0ID0gVFJVRSkgJT4lIAogIGZpbHRlcihuID4gMTUwKSAlPiUgCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUgCiAgZ2dwbG90KGFlcyhuLCB3b3JkKSkgKyAKICB0aGVtZV9taW5pbWFsKCkgKwogIGdlb21fY29sKGZpbGw9IiM3QjBEMUUiKSArIAogIGxhYnMoeSA9IE5VTEwpCmBgYAoKU2luY2UgdGhlc2UgdW5pZ3JhbXMgb25seSBjb252ZXkgd2hlcmUgcGFydGljaXBhbnRzIHdpbGwgZm9jdXMgdGhlaXIgY2hhbmdlcyB0byBwcmFjdGljZSwgSSBkZWNpZGVkIHRvIGFsc28gZXhhbWluZSBiaWdyYW1zIGhlcmUgdG8gZ2V0IGEgY2xlYXJlciBwaWN0dXJlIG9mIHRoZSBjaGFuZ2VzIHBhcnRpY2lwYW50cyBoYXZlIG1hZGUgdG8gdGhlaXIgY2xhc3Nyb29tIHByYWN0aWNlcy4KCmBgYHtyIGNoYW5nZS1iaWdyYW1zLCBjYWNoZT1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZW9jX2NoYW5nZXNfYmlncmFtcyA8LSBwcmFjdGljZV9jaGFuZ2VzICU+JQogIHVubmVzdF9uZ3JhbXMoYmlncmFtLCBDaGFuZ2VzVG9QcmFjdGljZSwgbiA9IDIsIHRvX2xvd2VyID0gVFJVRSkgCgplb2Nfc2VwYXJhdGVkX2NoYW5nZXMgPC0gZW9jX2NoYW5nZXNfYmlncmFtcyAlPiUgIAogIHNlcGFyYXRlKGJpZ3JhbSwgaW50byA9IGMoIndvcmQxIiwgIndvcmQyIiksIHNlcCA9ICIgIikgJT4lIAogIG5hLm9taXQoKQoKZW9jX3VuaXRlZF9jaGFuZ2VzIDwtIGVvY19zZXBhcmF0ZWRfY2hhbmdlcyAlPiUKICBmaWx0ZXIoISh3b3JkMSAlaW4lIHN0b3Bfd29yZHMkd29yZCksIAogICAgICAgICAhKHdvcmQyICVpbiUgc3RvcF93b3JkcyR3b3JkKSkgJT4lCiAgdW5pdGUoYmlncmFtLCBjKHdvcmQxLCB3b3JkMiksIHNlcCA9ICIgIikKCnRva2VuX2NvdW50c19jaGFuZ2VzIDwtICBlb2NfdGlkeV9jaGFuZ2VzICU+JSAKICBkcGx5cjo6Y291bnQod29yZCwgc29ydCA9IFRSVUUpCgpiaWdyYW1fY291bnRzX2NoYW5nZXMgPC0gZW9jX3VuaXRlZF9jaGFuZ2VzICU+JSAKICBkcGx5cjo6Y291bnQoYmlncmFtLCBzb3J0ID0gVFJVRSkgJT4lIAogIHRvcF9uKDI1KQpgYGAKCmBgYHtyIHdvcmRjbG91ZC1jaGFuZ2VzLCBmaWcuYWxpZ249J2NlbnRlcid9CndvcmRjbG91ZDIoYmlncmFtX2NvdW50c19jaGFuZ2VzLCBzaXplID0gMiwgc2hhcGUgPSAnY2lyY2xlJywgY29sb3IgPSAnIzdCMEQxRScpCmBgYAo8YnIgLz48YnIgLz4KVGhlIHRvcCAyNSBiaWdyYW1zIHNob3duIGluIHRoZSB3b3JkIGNsb3VkIGFib3ZlIHN1Z2dlc3QgdGhhdCBwYXJ0aWNpcGFudHMgaGF2ZSBhbHJlYWR5IG1hZGUgY2hhbmdlcyB0byB0aGVpciBwcm9mZXNzaW9uYWwgcHJhY3RpY2UgdGhhdCBpbmNsdWRlIGVzdGFibGlzaGluZyBub3JtcywgaG9sZGluZyBvZmZpY2UgaG91cnMsIG1ha2luZyBhbiBhY3Rpb24gcGxhbiBvciBsZXNzb24gcGxhbnMsIGNoZWNrIGlucywgcHJvdmlkaW5nIGZlZWRiYWNrLCBhbmQgdXNpbmcgR29vZ2xlIENsYXNzcm9vbS4gSG93ZXZlciwgbWFueSBvZiB0aGUgYmlncmFtcyBpbXBseSB0aGUgc2FtZSBjaGFuZ2VzIHdpdGggZGlmZmVyZW50IHdvcmRpbmdzLCBzdWNoIGFzICJwcm92aWRpbmcgZmVlZGJhY2siIGFuZCAicHJvdmlkZSBmZWVkYmFjayIgb3IgInZpcnR1YWwgbGVhcm5pbmciIGFuZCAib25saW5lIGxlYXJuaW5nLiIgVGhpcyBzdWdnZXN0cyB0aGF0IGZ1dHVyZSBhbmFseXNlcyBtYXkgYmVuZWZpdCBmcm9tIHN0ZW1taW5nLgoKIyMgUmVjb21tZW5kYXRpb25zIGZvciBJbXByb3ZlbWVudAoKVGhlIG5leHQgZ3VpZGluZyBxdWVzdGlvbiBmb3IgdGhpcyBjYXNlIHN0dWR5IGRlYWxzIHdpdGggcGFydGljaXBhbnRzJyByZWNvbW1lbmRhdGlvbnMgZm9yIGNvdXJzZSBpbXByb3ZlbWVudHM6IAoKKipJZiBwYXJ0aWNpcGFudHMgZm91bmQgdGhlIGNvdXJzZSB0byBiZSBpbmVmZmVjdGl2ZSwgd2hhdCBzcGVjaWZpYyByZWNvbW1lbmRhdGlvbnMgaGF2ZSB0aGV5IG1hZGUgZm9yIGl0cyBpbXByb3ZlbWVudD8qKgoKU3BlY2lmaWNhbGx5LCBpdCBmb2N1c2VzIG9uIHRoZSByZXNwb25zZXMgZnJvbSBwYXJ0aWNpcGFudHMgd2hvIHJhdGVkIHRoZSBvdmVyYWxsIGVmZmVjdGl2ZW5lc3Mgb2YgdGhlIGNvdXJzZSBhcyAqKk5laXRoZXIgZWZmZWN0aXZlIG5vciBpbmVmZmVjdGl2ZSoqLCAqKmluZWZmZWN0aXZlKiosIG9yICoqdmVyeSBpbmVmZmVjdGl2ZSoqLiBUaGUgcmVzcG9uc2UgdGV4dCBjb21lcyBmcm9tIHRoZSAqKkNvdXJzZVJlY29tbWVuZGF0aW9ucyoqIGNvbHVtbiBvZiB0aGUgZGF0YWZyYW1lLgoKYGBge3IgZ2V0LXJlY3N9CnBhcnRpY2lwYW50X3JlY29tbWVuZGF0aW9ucyA8LSBlb2Nfc3VydmV5X2RhdGEgJT4lCiAgc2VsZWN0KHJlc3BvbnNlLCBFZmZlY3RpdmVuZXNzUmF0aW5nLCBDb3Vyc2VSZWNvbW1lbmRhdGlvbnMpICU+JQogIG11dGF0ZShDb3Vyc2VSZWNvbW1lbmRhdGlvbnMgPSBnc3ViKCcmbmJzcDsnLCAnICcsIENvdXJzZVJlY29tbWVuZGF0aW9ucykpICU+JSAKICBtdXRhdGUoQ291cnNlUmVjb21tZW5kYXRpb25zID0gZ3N1YignJmFtcDsnLCAnICcsIENvdXJzZVJlY29tbWVuZGF0aW9ucykpICU+JQogIHNsaWNlKC0xLCAtMikgJT4lCiAgbmEub21pdCgpICU+JSAKICBmaWx0ZXIoQ291cnNlUmVjb21tZW5kYXRpb25zICE9ICdOL0EnLCAKICAgICAgICAgQ291cnNlUmVjb21tZW5kYXRpb25zICE9ICduL2EnLAogICAgICAgICBFZmZlY3RpdmVuZXNzUmF0aW5nID49IDMpCgpwYXJ0aWNpcGFudF9yZWNvbW1lbmRhdGlvbnMgJT4lIAogIHNlbGVjdChFZmZlY3RpdmVuZXNzUmF0aW5nLCBDb3Vyc2VSZWNvbW1lbmRhdGlvbnMpCmBgYAogCmBgYHtyIHRva2VuLXJlY3MsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJlY3Nfc3RvcCA8LSBkYXRhLmZyYW1lKCJ3b3JkIiA9IGMoIm4vYSIsICJOL0EiLCAiTi9hIikpCgplb2NfdGlkeV9yZWNzIDwtIHBhcnRpY2lwYW50X3JlY29tbWVuZGF0aW9ucyAlPiUKICB1bm5lc3RfdG9rZW5zKHdvcmQsIENvdXJzZVJlY29tbWVuZGF0aW9ucykgJT4lCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpICU+JSAKICBhbnRpX2pvaW4ocmVjc19zdG9wKQoKZW9jX3RpZHlfcmVjcyAlPiUgCiAgZHBseXI6OmNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKSAlPiUgCiAgZmlsdGVyKG4gPiAyKSAlPiUgCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUgCiAgZ2dwbG90KGFlcyhuLCB3b3JkKSkgKyAKICB0aGVtZV9taW5pbWFsKCkgKwogIGdlb21fY29sKGZpbGw9IiM3QjBEMUUiKSArIAogIGxhYnMoeSA9IE5VTEwpIApgYGAKIApBZnRlciB0b2tlbml6YXRpb24sIHRoZSB3b3JkcyBtb3N0IGZyZXF1ZW50bHkgdXNlZCBpbiByZXNwb25zZSB0byB0aGUgc3VydmV5IHF1ZXN0aW9uICJXaGF0IHJlY29tbWVuZGF0aW9ucyBkbyB5b3UgaGF2ZSBmb3IgbWFraW5nIHRoaXMgY291cnNlIG1vcmUgdmFsdWFibGUgdG8gZnV0dXJlIHBhcnRpY2lwYW50cz8iIGFyZSB3b3JkcyBsaWtlIHZpZGVvcywgdGltZSwgdGVhY2hlcnMsIHJlc291cmNlcy4gSW4gZmFjdCwgb24gdGhlIHdob2xlIHRoZSB0b2tlbml6ZWQgdGV4dCBjbG9zZWx5IHJlc2VtYmxlcyB0aGUgcmVzdWx0cyBmcm9tIGV4YW1pbmluZyB0aGUgb3RoZXIgdGV4dCByZXNwb25zZXMuIFRoZXJlZm9yZSwgYSBjbG9zZXIgbG9vayBpbnRvIHRoZSByYXcgZGF0YSBtYXkgYmUgaGVscGZ1bC4gV2UnbGwgZ3JhYiBhIHNhbXBsaW5nIG9mIHRoZSByZXNwb25zZXMgZnJvbSB0aGUgcmF0aW5ncyBvZiAqKk5laXRoZXIgZWZmZWN0aXZlIG5vciBpbmVmZmVjdGl2ZSoqLCAqKmluZWZmZWN0aXZlKiosIG9yICoqdmVyeSBpbmVmZmVjdGl2ZSoqIGFuZCByZWFkIHRocm91Z2ggdGhlbS4KCmBgYHtyIHNhbXBsZS1yZWNzfQpyZWNzX3F1b3RlcyA8LSBwYXJ0aWNpcGFudF9yZWNvbW1lbmRhdGlvbnMgJT4lIAogIHNlbGVjdChyZXNwb25zZSwgRWZmZWN0aXZlbmVzc1JhdGluZywgQ291cnNlUmVjb21tZW5kYXRpb25zKSAlPiUgCiAgZmlsdGVyKEVmZmVjdGl2ZW5lc3NSYXRpbmcgPj0gMywKICAgICAgICAgQ291cnNlUmVjb21tZW5kYXRpb25zICE9ICdub25lJywKICAgICAgICAgQ291cnNlUmVjb21tZW5kYXRpb25zICE9ICdOL2EnKQoKc2FtcGxlX25ldXRyYWwgPC0gcmVjc19xdW90ZXMgJT4lIAogIGZpbHRlcihFZmZlY3RpdmVuZXNzUmF0aW5nID09IDMpICU+JSAKICBzYW1wbGVfbig1KSAlPiUgCiAgc2VsZWN0KENvdXJzZVJlY29tbWVuZGF0aW9ucykKCnNhbXBsZV9pbmVmZmVjdGl2ZSA8LSByZWNzX3F1b3RlcyAlPiUgCiAgZmlsdGVyKEVmZmVjdGl2ZW5lc3NSYXRpbmcgPT0gNCkgJT4lIAogIHNlbGVjdChDb3Vyc2VSZWNvbW1lbmRhdGlvbnMpCgpzYW1wbGVfdmVyeWluZWZmZWN0aXZlIDwtIHJlY3NfcXVvdGVzICU+JSAKICBmaWx0ZXIoRWZmZWN0aXZlbmVzc1JhdGluZyA9PSA1KSAlPiUgCiAgc2FtcGxlX24oNSkgJT4lIAogIHNlbGVjdChDb3Vyc2VSZWNvbW1lbmRhdGlvbnMpCiAgCnNhbXBsZV9yZWNzIDwtIHJiaW5kKHNhbXBsZV9uZXV0cmFsLCBzYW1wbGVfaW5lZmZlY3RpdmUsIHNhbXBsZV92ZXJ5aW5lZmZlY3RpdmUpCgprYWJsZShzYW1wbGVfcmVjcykKYGBgCgpSZWFkaW5nIHRocm91Z2ggdGhlc2UgcmVzdWx0cywgc29tZSBrZXkgaXNzdWVzIGFyZSBoaWdobGlnaHRlZCBpbiB0aGVzZSByZXNwb25zZXMuIEZvciBleGFtcGxlLCBtdWx0aXBsZSBwYXJ0aWNpcGFudHMgaW4gdGhpcyBzYW1wbGUgc3VnZ2VzdHMgYSBsYWNrIG9mIGNvdXJzZSBjb250ZW50IGFkZHJlc3NpbmcgcmVtb3RlIHRlYWNoaW5nIHN0cmF0ZWdpZXMgZm9yIHN1cHBvcnRpbmcgc3R1ZGVudHMgd2l0aCBkaXNhYmlsaXRpZXMuIE90aGVyIHJlc3BvbnNlcyBzdWdnZXN0IHRoYXQgdGhlIGNvdXJzZSBuZWVkZWQgbW9yZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHBhcnRpY2lwYW50cyBvciB0aGF0IGNvdXJzZSBjb250ZW50IHdhcyB0b28gbG9uZyBhbmQvb3IgcmVwZXRpdGl2ZS4gSG93ZXZlciwgYW5kIHBlcmhhcHMgc29tZXdoYXQgc3VycHJpc2luZ2x5LCBzb21lIHJlc3BvbnNlcyBzdWdnZXN0IHRoYXQgdGhlIGNvdXJzZSBpcyBzdWZmaWNpZW50IGFuZCB2ZXJ5IHZhbHVhYmxlIGRlc3BpdGUgbG93IG92ZXJhbGwgZWZmZWN0aXZlbmVzcyByYXRpbmdzLiBUaHVzLCB0aGUgbmV4dCBzdGVwIGluIHRoaXMgY2FzZSBzdHVkeSB3aWxsIGJlIHRvIHBlcmZvcm0gc2VudGltZW50IGFuYWx5c2lzIG9uIHRoZSBwYXJ0aWNpcGFudHMnIHRleHQgcmVzcG9uc2VzIGFuZCBjb21wYXJlIHRoYXQgdG8gdGhlIG92ZXJhbGwgZWZmZWN0aXZlbmVzcyByYXRpbmdzIHRoYXQgcGFydGljaXBhbnRzIGdhdmUgdG8gdGhlIGNvdXJzZS4KCiMjIFBhcnRpY2lwYW50cycgU2VudGltZW50cyBDb21wYXJlZCB0byBDb3Vyc2UgUmF0aW5ncwoKVGhlIGZpbmFsIGd1aWRpbmcgcXVlc3Rpb24gZm9yIHRoaXMgc3R1ZHkgaXM6CgoqKkhvdyBkbyB0aGUgc2VudGltZW50cyBvZiBwYXJ0aWNpcGFudHMnIG9wZW4tZW5kZWQgcmVzcG9uc2VzIGNvbXBhcmUgdG8gdGhlaXIgcmF0aW5ncyBvZiB0aGUgY291cnNlJ3Mgb3ZlcmFsbCBlZmZlY3RpdmVuZXNzPyoqCgpUbyBhbnN3ZXIgdGhpcyBxdWVzdGlvbiwgdGhlIHJlc3BvbnNlIHRleHQgb2YgYWxsIHRocmVlIG9wZW4tZW5kZWQgc3VydmV5IGl0ZW1zIHdhcyBjb21iaW5lZCBpbnRvIGEgc2luZ2xlIHRleHQgZW50cnkgZm9yIGVhY2ggc3VydmV5IHJlc3BvbnNlLiBBZGRpdGlvbmFsbHksIHBhcnRpY2lwYW50cycgcmF0aW5ncyBmb3IgdGhlIGNvdXJzZSdzIG92ZXJhbGwgZWZmZWN0aXZlbmVzcyB3ZXJlIGFkYXB0ZWQgZnJvbSB0aGUgNS1wb2ludCBMaWtlcnQgc2NhbGUgKCoqdmVyeSBlZmZlY3RpdmUqKiB0byAqKnZlcnkgaW5lZmZlY3RpdmUqKikgdG8gYSAzLXBvaW50IHNlbnRpbWVudCBzY2FsZS4gVGhhdCBpcywgcmF0aW5ncyBvZiAqKnZlcnkgZWZmZWN0aXZlKiogYW5kICoqZWZmZWN0aXZlKiogd2VyZSBjb2xsYXBzZWQgdG8gcmVwcmVzZW50ICoqcG9zaXRpdmUqKiBzZW50aW1lbnQsICoqbmVpdGhlciBlZmZlY3RpdmUgbm9yIGluZWZmZWN0aXZlKiogcmVwcmVzZW50cyBhICoqbmV1dHJhbCoqIHNlbnRpbWVudCwgYW5kICoqdmVyeSBpbmVmZmVjdGl2ZSoqIGFuZCAqKmluZWZmZWN0aXZlKiogd2VyZSBjb2xsYXBzZWQgdG8gcmVwcmVzZW50IGEgKipuZWdhdGl2ZSoqIHNlbnRpbWVudC4gVGhlbiBwcm9wb3J0aW9ucyBvZiB0aGUgcmVzdWx0aW5nIGNvdXJzZSByYXRpbmcgc2VudGltZW50cyB3ZXJlIGNhbGN1bGF0ZWQgdG8gbWFrZSBjb21wYXJpc29uIHRvIHRoZSByZXN1bHRzIG9mIHNlbnRpbWVudCBhbmFseXNpcyB1c2luZyB0aGUgW1ZhbGVuY2UgQXdhcmUgRGljdGlvbmFyeSBhbmQgc0VudGltZW50IFJlYXNvbmVyIChWQURFUikgcGFja2FnZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3ZhZGVyL2luZGV4Lmh0bWwpLgoKYGBge3IgY291cnNlLXJhdGluZ3MsIGNhY2hlPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvdXJzZVJhdGluZ3NfcmVzdWx0cyA8LSBlb2Nfc3VydmV5X2RhdGEgJT4lCiAgbXV0YXRlKHNlbnRpbWVudCA9IGlmZWxzZShFZmZlY3RpdmVuZXNzUmF0aW5nID09IDUsICJuZWdhdGl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFZmZlY3RpdmVuZXNzUmF0aW5nID09IDQsICJuZWdhdGl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRWZmZWN0aXZlbmVzc1JhdGluZyA9PSAzLCAibmV1dHJhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEVmZmVjdGl2ZW5lc3NSYXRpbmcgPT0gMiwgInBvc2l0aXZlIiwgInBvc2l0aXZlIikpKSkpICU+JQogIGRwbHlyOjpjb3VudChzZW50aW1lbnQsIHNvcnQgPSBUUlVFKSAlPiUKICBuYS5vbWl0KCkgJT4lIAogIG11dGF0ZShwcm9wb3J0aW9uID0gbiAvIHN1bShuKSkgJT4lIAogIG11dGF0ZShsZXhpY29uID0gIlBhcnRpY2lwYW50IFJhdGluZyBTZW50aW1lbnQiKSAKCmNvdXJzZVJhdGluZ3NfcmVzdWx0cwpgYGAKIApgYGB7ciB2YWRlci1zZW50aW1lbnRzLCBjYWNoZT1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdXJ2ZXlfcmVzcF90ZXh0IDwtIGVvY19zdXJ2ZXlfZGF0YQoKc3VtbWFyeV92YWRlciA8LSB2YWRlcjo6dmFkZXJfZGYoc3VydmV5X3Jlc3BfdGV4dCR0ZXh0KSAlPiUgCiAgc2VsZWN0KHRleHQsIGNvbXBvdW5kLCBwb3MsIG5lZywgbmV1KQoKdmFkZXJfcmVzdWx0cyA8LSBzdW1tYXJ5X3ZhZGVyICU+JQogIG11dGF0ZShzZW50aW1lbnQgPSBpZmVsc2UoY29tcG91bmQgPiAwLCAicG9zaXRpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGNvbXBvdW5kIDwgMCwgIm5lZ2F0aXZlIiwgIm5ldXRyYWwiKSkpICU+JQogIGRwbHlyOjpjb3VudChzZW50aW1lbnQsIHNvcnQgPSBUUlVFKSAlPiUKICBuYS5vbWl0KCkgJT4lCiAgbXV0YXRlKHByb3BvcnRpb24gPSBuIC8gc3VtKG4pKSAlPiUKICBtdXRhdGUobGV4aWNvbiA9ICJWYWRlciBTZW50aW1lbnQiKQoKdmFkZXJfcmVzdWx0cwpgYGAKCkFzIHlvdSBjYW4gc2VlIGZyb20gdGhlIHJlc3VsdHMgYmVsb3csIHRoZSBzZW50aW1lbnQgYW5hbHlzaXMgb2YgdGhlIG9wZW4tZW5kZWQgcmVzcG9uc2VzIGFwcGVhcnMgdG8gYWxpZ24gd2l0aCB0aGUgc2VudGltZW50cyBvZiBwYXJ0aWNpcGFudHMnIGNvdXJzZSByYXRpbmdzLiBUaGlzIGlzIGRlc3BpdGUgc29tZSByZXN1bHRzIGFib3ZlIHdoZXJlIHBhcnRpY2lwYW50cyByYXRlZCB0aGUgY291cnNlIHRvIGJlICoqaW5lZmZlY3RpdmUqKiBvciAqKm5laXRoZXIgZWZmZWN0aXZlIG5vciBpbmVmZmVjdGl2ZSoqIGJ1dCBzdGF0ZWQgdGhhdCB0aGV5IGxpa2VkIHRoZSBjb3Vyc2UgYXMgaWYgYW5kIHdvdWxkIG5vdCByZWNvbW1lbmQgY2hhbmdlcy4gCgpgYGB7ciBzZW50aW1lbnQtY29tcGFyaXNvbiwgY2FjaGU9VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY29tcGFyaXNvbl9kZiA8LSByYmluZCh2YWRlcl9yZXN1bHRzLCBjb3Vyc2VSYXRpbmdzX3Jlc3VsdHMpCgpnZ3Bsb3QoY29tcGFyaXNvbl9kZiwgYWVzKHggPSBzZW50aW1lbnQsIHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gc2VudGltZW50KSkgKwogIGdlb21fY29sKCkgKwogIGZhY2V0X2dyaWQoLiB+IGxleGljb24pICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogIHhsYWIoIlNlbnRpbWVudCIpICsKICB5bGFiKCJQcm9wb3J0aW9uIikgKwogIGdndGl0bGUoIlNlbnRpbWVudCBDb21wYXJpc29uIG9mIFBhcnRpY2lwYW50cycgUmF0aW5ncyBhbmQgVmFkZXIgQW5hbHlzaXMgUmVzdWx0cyIpCmBgYAoKRm9yIGEgZGVlcGVyIGxvb2sgYXQgcGFydGljaXBhbnRzJyBzZW50aW1lbnRzIGFzIGV4cHJlc3NlZCB0aHJvdWdoIHRoZWlyIHRleHQgcmVzcG9uc2VzLCBJIGFsc28gZGVjaWRlZCB0byB1c2UgdGhlICoqTlJDKiogc2VudGltZW50IGxleGljb24gdG8gZXhhbWluZSB0aGUgcmFuZ2Ugb2YgZW1vdGlvbnMgZXhwcmVzc2VkIGFjcm9zcyB0aGUgc3VydmV5IHJlc3BvbnNlcy4gVGhlIHJlc3VsdHMgb2YgdGhpcyBhbmFseXNpcyBhcmUgc2hvd24gYmVsb3cuCgpgYGB7ciBucmMtc2VudGltZW50cywgY2FjaGU9VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbnJjIDwtIGdldF9zZW50aW1lbnRzKCJucmMiKQoKc3VydmV5X3N0b3AgPC0gZGF0YS5mcmFtZSgid29yZCIgPSBjKCJuYnNwIiwgIk5BIiwgIk4vQSIsICJuL2EiLCAibmEiLCAiYW1wIikpCgpwYXJ0aWNpcGFudF90b2tlbnMgPC0gZW9jX3N1cnZleV9kYXRhICU+JQogIHNlbGVjdChyZXNwb25zZSwgdGV4dCkgJT4lCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0KSAlPiUKICBhbnRpX2pvaW4oc3RvcF93b3JkcykgJT4lCiAgYW50aV9qb2luKHN1cnZleV9zdG9wKQoKc2VudGltZW50X25yYyA8LSBpbm5lcl9qb2luKHBhcnRpY2lwYW50X3Rva2VucywgbnJjLCBieSA9ICJ3b3JkIikKCnN1bW1hcnlfbnJjIDwtIHNlbnRpbWVudF9ucmMgJT4lCiAgZHBseXI6OmNvdW50KHNlbnRpbWVudCwgc29ydCA9IFRSVUUpICU+JQogIHNwcmVhZChzZW50aW1lbnQsIG4pICU+JQogIG11dGF0ZShsZXhpY29uID0gIm5yYyIpICU+JQogIHJlbG9jYXRlKGxleGljb24pICU+JSAKICBzZWxlY3QoYW5nZXIsIGFudGljaXBhdGlvbiwgZGlzZ3VzdCwgZmVhciwgam95LCBzYWRuZXNzLCBzdXJwcmlzZSwgdHJ1c3QpCgprYWJsZShzdW1tYXJ5X25yYykKYGBgCgpBcyB5b3UgY2FuIHNlZSwgcGFydGljaXBhbnRzJyBtb3N0IGZyZXF1ZW50bHkgZXhoaWJpdGVkIHRydXN0IGluIHRoZWlyIHJlc3BvbnNlcyBhbG9uZyB3aXRoIGFudGljaXBhdGlvbiBhbmQgam95LiBUaGUgbGVhc3QgZnJlcXVlbnQgZW1vdGlvbnMgZXhoaWJpdGVkIHdlcmUgYW5nZXIgYW5kIGRpc2d1c3QuIEFnYWluLCB0aGVzZSByZXN1bHRzIHN1cHBvcnQgdGhhdCwgb2YgdGhvc2UgcGFydGljaXBhbnRzIHdobyByZXNwb25kZWQgdG8gdGhlIGVuZCBvZiBjb3Vyc2Ugc3VydmV5LCBvdmVyYWxsIHNhdGlzZmFjdGlvbiB3aXRoIHRoZSBjb3Vyc2UgY29udGVudCB3YXMgc2tld2VkIHZlcnkgcG9zaXRpdmVseS4KClNpbmNlIHRoZSBjb3Vyc2UgcmF0aW5ncyBhbmQgc2VudGltZW50cyBhcmUgc2tld2VkIHNvIHBvc2l0aXZlbHkgYW5kIGEgc3RhdGVkIGxpbWl0YXRpb24gb2YgdGhpcyBkYXRhIGlzIGEgcG90ZW50aWFsbHkgbG93IHJlc3BvbnNlIHJhdGUgZm9yIHRob3NlIHdobyBkaWQgbm90IGNvbXBsZXRlIHRoZSBjb3Vyc2UgYWN0aXZpdGllcywgd2UnbGwgZXhhbWluZSB0aGUgcHJvcG9ydGlvbiBvZiByZXNwb25zZXMgdGhhdCBpbmRpY2F0ZSBwYXJ0aWNpcGFudHMnIGFiaWxpdHkgdG8gY29tcGxldGUgYWxsIHRoZSBhY3Rpdml0aWVzIHRoZXkgd2FudGVkIHRvIGNvbXBsZXRlIGR1cmluZyB0aGUgY291cnNlLiBUaGUgc3VydmV5IGl0ZW0gdGhhdCBwcm92aWRlcyB0aGUgZGF0YSBmb3IgdGhpcyBwYXJ0IG9mIHRoZSBhbmFseXNpcyBpcyB0aGUgeWVzIG9yIG5vIHF1ZXN0aW9uOgoKKipXZXJlIHlvdSBhYmxlIHRvIGNvbXBsZXRlIGFsbCBvZiB0aGUgYWN0aXZpdGllcyB0aGF0IHlvdSB3YW50ZWQgdG8gY29tcGxldGUgaW4gdGhpcyBjb3Vyc2U/KioKCk5vdGUgaGVyZSB0aGF0IHdlIGFyZSBjb25zaWRlcmluZyBhIHllcyByZXNwb25zZSB0byBtZWFuICJjb21wbGV0ZSIgYW5kIGEgbm8gcmVzcG9uc2UgdG8gbWVhbiAiaW5jb21wbGV0ZS4iIAoKYGBge3IgY291cnNlLWNvbXBsZXRpb259Cgpjb3Vyc2VDb21wbGV0aW9uX3Jlc3VsdHMgPC0gZW9jX3N1cnZleV9kYXRhICU+JSAKICBzZWxlY3QoQ291cnNlQ29tcGxldGlvbikgJT4lIAogIGRwbHlyOjpjb3VudChDb3Vyc2VDb21wbGV0aW9uLCBzb3J0ID0gVFJVRSkgJT4lCiAgbXV0YXRlKHByb3BvcnRpb24gPSBuIC8gc3VtKG4pKQoKa2FibGUoY291cnNlQ29tcGxldGlvbl9yZXN1bHRzKQoKYGBgCkFzIHlvdSBjYW4gc2VlIGluIHRoZSB0YWJsZSBhYm92ZSwgYXBwcm94aW1hdGVseSA0IHBlcmNlbnQgb2YgdGhlIHJlc3BvbnNlcyB3ZXJlIGZyb20gcGFydGljaXBhbnRzIHdobyB3ZXJlIHVuYWJsZSB0byBjb21wbGV0ZSBhbGwgb2YgdGhlIGNvdXJzZSBhY3Rpdml0aWVzIGFzIHRoZXkgZGVzaXJlZC4gVGhpcyBtYXkgZXhwbGFpbiB3aHkgdGhlIHNlbnRpbWVudCByZXN1bHRzIGFyZSBza2V3ZWQgc28gcG9zaXRpdmVseS4gCgojIERpc2N1c3Npb24KCkRlc3BpdGUgdGhlIHNob3J0IGFtb3VudCBvZiB0ZXh0IHByb3ZpZGVkIGJ5IHRoZSBwYXJ0aWNpcGFudHMnIHJlc3BvbnNlcyB0byB0aGUgb3Blbi1lbmRlZCBxdWVzdGlvbnMgb24gdGhlIGVuZCBvZiBjb3Vyc2Ugc3VydmV5cywgdGhlcmUgYXJlIHN0aWxsIGtleSBpbnNpZ2h0cyB0byBiZSBnYWluZWQgdGhhdCB3aWxsIGFpZCByZWZpbmVtZW50cyB0byBvdXIgcHJvZmVzc2lvbmFsIGxlYXJuaW5nIE1PT0MtRWQgY291cnNlIG9uIFRlYWNoaW5nIFJlbW90ZWx5LiBJbiBwYXJ0aWN1bGFyLCBzb21lIGhpZ2hsaWdodHMgZnJvbSB0aGUgYW5hbHlzaXMgYXJlOgoKLSBQYXJ0aWNpcGFudHMgZm91bmQgY29udGVudCBzdWNoIGFzIGFjdGlvbiBwbGFucywgbGVhcm5pbmcgZ29hbHMsIHVuaXQgNSwgYW5kIHVuaXQgNiB0byBiZSBwYXJ0aWN1bGFybHkgdmFsdWFibGUgYXNwZWN0cyBvZiB0aGUgY291cnNlLgotIFBhcnRpY2lwYW50cyBleHByZXNzZWQgY2xlYXIgcGxhbnMgZm9yIGFwcGx5aW5nIGNvdXJzZSBjb250ZW50IHRvIHRoZWlyIG93biBwcm9mZXNzaW9uYWwgcHJhY3RpY2UgYW5kIGFyZSBhbHJlYWR5IGRvaW5nIHNvIHdpdGggcHJhY3RpY2VzIHN1Y2ggYXMgZXN0YWJsaXNoaW5nIG5vcm1zIGZvciB0aGVpciB2aXJ0dWFsIGNsYXNzcm9vbXMsIGhvbGRpbmcgb2ZmaWNlIGhvdXJzIGFuZCBjaGVjayBpbnMsIHByb3ZpZGluZyBmZWVkYmFjaywgYW5kIHVzaW5nIEdvb2dsZSBDbGFzc3Jvb20uCi0gQ291cnNlIGNvbnRlbnQgbWF5IGJlbmVmaXQgZnJvbSBpZGVudGlmeWluZyByZWR1bmRhbnQgbWF0ZXJpYWwgaW4gYW4gZWZmb3J0IHRvIHNob3J0ZW4gdGltZSBzcGVudCwgaW5jbHVkaW5nIG1vcmUgcGFydGljaXBhbnQgcGVlciBpbnRlcmFjdGlvbiwgb3IgYWRkaW5nIGNvbnRlbnQgdGhhdCBhZGRyZXNzaW5nIHJlbW90ZSB0ZWFjaGluZyBzdXBwb3J0cy9yZXNvdXJjZXMgZm9yIHRob3NlIHdpdGggc3R1ZGVudHMgd2hvIGhhdmUgc3BlY2lhbCBuZWVkcywgc3VjaCBhcyBzdHVkZW50cyB3aXRoIGRpc2FiaWxpdGllcy4KLSBPbiB0aGUgd2hvbGUsIGNvdXJzZSByYXRpbmdzIHdlcmUgdmVyeSBwb3NpdGl2ZSBhbmQgdGhlIHNlbnRpbWVudHMgZXhwcmVzc2VkIGJ5IHBhcnRpY2lwYW50cyB3cml0dGVuIHJlc3BvbnNlcyBhZ3JlZWQgd2l0aCB0aGVzZSByYXRpbmdzLgoKRGVzcGl0ZSBnYWluaW5nIHRoZXNlIHZlcnkgdXNlZnVsIGluc2lnaHRzIGZyb20gdGhlIGVuZCBvZiBjb3Vyc2Ugc3VydmV5IHJlc3BvbnNlcywgd2Ugc2hvdWxkIGNvbnNpZGVyIHRoYXQgc29tZSBpbnNpZ2h0cyBtYXkgYmUgbWlzc2luZyBkdWUgdG8gdGhlIGxvdyByZXNwb25zZSByYXRlcyBmb3IgdGhvc2Ugd2hvIHdlcmUgdW5hYmxlIHRvIGNvbXBsZXRlIHRoZSBjb3Vyc2UuIEZpbmFsbHksIHRoZSByZXN1bHRzIHN1Z2dlc3QgdGhhdCBmdXJ0aGVyIHRleHQgbWluaW5nIGFuYWx5c2lzIG1heSBiZW5lZml0IGZyb20gc3RlbW1pbmcgdGhlIHRva2VuaXplZCBkYXRhLgoKIyBUaGUgQXV0aG9yCgohW10oamVubi5qcGcpe3dpZHRoPSIxNDVweCIgc3R5bGU9ImZsb2F0OiBsZWZ0OyBtYXJnaW4tcmlnaHQ6IDMwcHg7IG1hcmdpbi10b3A6IDVweDsifQoKSmVubmlmZXIgSG91Y2hpbnMgaXMgYSBkb2N0b3JhbCBjYW5kaWRhdGUgaW4gTGVhcm5pbmcgRGVzaWduIGFuZCBUZWNobm9sb2d5IGF0IE5vcnRoIENhcm9saW5hIFN0YXRlIFVuaXZlcnNpdHkuIEhlciByZXNlYXJjaCBleGFtaW5lcyBzdHVkZW50cycgdXNlIG9mIGNvbXB1dGF0aW9uYWwgdGhpbmtpbmcgYW5kIHRoZSBlZmZlY3RpdmUgdXNlIG9mIGluc3RydWN0aW9uYWwgdGVjaG5vbG9neSB0byBkZWVwZW4gY29uY2VwdHVhbCB1bmRlcnN0YW5kaW5nIGluIGJvdGggZm9ybWFsIGFuZCBpbmZvcm1hbCBLLTEyIGxlYXJuaW5nIGVudmlyb25tZW50cy4gU2hlIGN1cnJlbnRseSBhIGdyYWR1YXRlIHJlc2VhcmNoIGFzc2lzdGFudCBmb3IgdGhlIFtJbmZ1c2VDUyBwcm9qZWN0XShodHRwOi8vcHJvamVjdHMuaW50ZWxsaW1lZGlhLm5jc3UuZWR1L2luZnVzZWNzLyksIHRoZSBbUHJvZ3JhbW1lZCBSb2JvdGljcyBpbiB0aGUgU2Nob29sIE1ha2Vyc3BhY2UgKFBSSVNNKSBwcm9qZWN0XShodHRwczovL3Byb2dyYW1tZWRyb2JvdGljcy53ZWVibHkuY29tLyksIGFuZCB0aGUgW0ZyaWRheSBJbnN0aXR1dGUncyBQcm9ncmFtIEV2YWx1YXRpb24gYW5kIEVkdWNhdGlvbiBSZXNlYXJjaCAoUEVFUikgR3JvdXBdKGh0dHBzOi8vd3d3LmZpLm5jc3UuZWR1L3RlYW1zL3BlZXIvKS4KCipZb3UgY2FuIGxlYXJuIG1vcmUgYWJvdXQgSmVubmlmZXIgYW5kIGhlciB3b3JrIGJ5IFt2aXNpdGluZyBoZXIgd2Vic2l0ZV0oaHR0cHM6Ly9qZW5uaWZlcmtob3VjaGlucy5jb20pLiBZb3UgY2FuIGFsc28gZm9sbG93IGhlciBvbiBgciBmb250YXdlc29tZTo6ZmFfaSgndHdpdHRlcicpYCBbQFRvb1N3ZWV0R2Vla10oaHR0cHM6Ly90d2l0dGVyLmNvbS9Ub29Td2VldEdlZWspLiogCgojIEFja25vd2xlZGdlbWVudHMKClRoaXMgcHJvamVjdCB1c2VzIHRlY2huaXF1ZXMgZnJvbSBbKlRleHQgTWluaW5nIHdpdGggUjogQSBUaWR5IEFwcHJvYWNoKl0oaHR0cHM6Ly93d3cudGlkeXRleHRtaW5pbmcuY29tLykgYnkgSnVsaWEgU2lsZ2UgYW5kIERhdmlkIFJvYmluc29uLiBTcGVjaWFsIHRoYW5rcyB0byBvdXIgY291cnNlIGluc3RydWN0b3IsIERyLiBTaGF1biBLZWxsb2dnLCBmb3IgdGhlIHNlbnNlIG9mIGNvbW11bml0eSBjcmVhdGVkIGZvciB0aGlzIGNvdXJzZSBhcyB3ZSBhbGwgd29ya2VkIHRvIGxlYXJuIFIgdGV4dCBtaW5pbmcgdGVjaG5pcXVlcyB0b2dldGhlci4KCiMgRW5kIG9mIFNlbWVzdGVyIEZlZWxzCgpCb251cyBDb250ZW50OiBUaGlzIGlzIEplbm4uIFNoZSBpcyBoYXBweSB0byBiZSBkb25lIHdpdGggdGhpcyBjcmF6eSBzdHJlc3NmdWwgeWVhci4KCiFbXShodHRwczovL21lZGlhLmdpcGh5LmNvbS9tZWRpYS9wcUN4TDQzd2hES3pTL2dpcGh5LmdpZikK